Image courtesy of the NCAA
Introduction
This project will build on one that I began in March of 2025,
predicting the outcomes of March Madness tournament games.
March Madness is a single-elimination basketball tournament
featuring 68 teams, with representatives from every conference in
Division I NCAA basketball. The 68-team pool is narrowed down to 64
after eight teams play each other in the “First Four” round. Within this
field of 64, they’re split between four “regions” of a bracket,
South, West, East,
and Midwest. The teams in each region are ranked by the
NCAA Committee and given a “seed” between #1 and #16. Those teams are
then matched up against each other so that #1 plays #16, #2 plays #15,
#3 plays #14, and so on. We’ll revisit the seeding and team breakdown
later, but this should give those unfamiliar with the tournament a
general idea of the format.
Each year, once the field of 64 is established, tens of millions
around the world try their best to predict the winners and losers of
each game across all 67 that are played throughout the tournament, which
narrows the field down to just two teams who will play for the National
Championship title. To this day, nobody has ever correctly predicted all
67 outcomes perfectly. According
to the NCAA, the closest anyone has ever come to a perfect bracket
was Gregg Nigl, a neuropsychologist from Columbus, Ohio who correctly
predicted the outcomes of 49 straight games before #3 Purdue defeated #2
Tennessee in overtime of the second game in the Sweet 16.
This year, I decided to take a more analytical approach to building
my own bracket. After three days of researching predictive values in
basketball, reading papers, and journaling all of my findings, I found a
blog
post from 2021 about an R Project using a binomial distribution
approach I hadn’t seen anywhere else before. I tried my best to emulate
that procedure with my limited abilities at the time, but in the end was
unsatisfied with the uncertain quality of my work. I elected not to
embarrass myself by subjecting this model to the scrutiny of my peers,
and kept the results buried in an almost indecipherable spreadsheet.
This uncertainty proved to be foolish, however, as all of that work done
exclusively in Microsoft Excel and several pages of handwritten notes
was able to correctly predict 56/67 outcomes across the
entire tournament. The goal, unfortunately, is a perfect
67/67. This challenge has stumped mathematicians,
economists, analysts, and everyday basketball fans alike for decades.
The question that everyone asks each March is the same, “what teams are
going to pull off an upset?”
If choosing a perfect bracket were as simple as picking the
“favorite” in each game by their seeding, we’d expect to see a Final
Four of four #1 seeds every year, but we know that’s not the case. In
fact, it’s only happened twice: 2008’s Final Four
featured #1 seeds Kansas, Memphis, North Carolina, and UCLA. The only
other year it’s happened? 2025. This year’s Final Four
of #1 seeds Auburn, Duke, Florida, and Houston achieved that feat for
just the second time ever. Despite this, we enter the 2025-26 College
Basketball season with nobody ever correctly crafting a perfect
bracket.
So, what teams pulled off an “upset”? To answer that question we
first need to split it into two parts. Which teams were
actually favored in each game, and who won? The latter is easy
to answer, as each game was played in March/April of 2025, and we have
all the results readily available. The former, not so much. In order to
start answering that question, let’s set the stage.
The Bracket
Each team in the March Madness tournament is vying for a
chance to play in the National Championship. Those 68 teams are selected
from the pool of all 364 Division I teams in the NCAA. Each of the 364
schools are split into 31 different conferences, who primarily compete
against the other members of their conference in the regular season. At
the conclusion of the regular season each conference hosts their own
single-elimination tournament, and the winner of that tournament
receives an “automatic bid” to play in the March Madness
tournament. The remaining 37 spots in the tournament are decided by the
NCAA Committee, who awards “at-large” bids. These go to whichever teams
they deem to be the 37 best in the country, but didn’t win their
conference and receive an automatic bid.
For a number of reasons, this selection process is where the
“madness” begins. Any team in the country, regardless of how bad they
were throughout the regular season, just needs to qualify for their
conference tournament to have a shot at dancing. If they can get hot in
their conference tournament and win it, they receive an automatic bid
all the same. We’ll take a look at the data in the next section and
where it comes from, but one of the “worst” teams in the tournament this
year, the Saint Francis Red Flash, had a pedestrian 13-17 overall record
heading into the Northeast Conference (NEC) Tournament. Despite this,
they were able to secure wins over Wagner, LIU, and Central Connecticut
to win the NEC and punch their ticket to be a part of the madness.
As we can see, the auto-bid system introduces a level of chaos in
terms of who is able to qualify for the tournament. Mount
St. Mary’s, another auto-bid team out of the MAAC (Metro Atlantic
Athletic Conference) was matched up with blue-blood basketball program
Duke in the Round of 64. With an undergraduate student body of 1,815,
Mount St. Mary’s has absolutely no business playing Duke in a nationally
televised basketball game, and suffered an uncompetitive 93-49 defeat.
Despite the clear discrepancies in some matchups, the auto-bid system
affords the smaller conferences/schools an equal opportunity to make an
appearance in the tournament.
When a national powerhouse like Duke squares off against a small,
private, liberal arts school from rural Maryland, we can reasonably
assume who’s going to win that game. While that’s not always the case
(see 2018 #1 Virginia vs. #16 UMBC, another #16 seed from Maryland who
achieved a much different result), we generally expect the smaller
conferences to struggle against their much larger counterparts. The
at-large bid system, on the other hand, introduces a considerable amount
of uncertainty to the bracket for a different reason. The NCAA
Committee’s exact approach to determining the 37 “best” remaining
schools in the country, after all the auto-bids have been awarded, has
been the subject of much debate throughout the tournament’s entire
existence. We can reasonably assume that they use much of the same
criteria that we will use in our own data, but they have an illustrious
history of being “wrong” when making those selections. Since the
selection process of at-large bids isn’t the topic of this project, we
won’t go too in-depth into who receives them. All we need to understand
about these at-large teams is that they are believed to have
earned their bid through their play across the entire season,
and their seeding should reflect how good of a team they are. For
instance, Auburn lost in the semifinals of the SEC (Southeastern
Conference) Tournament to Tennessee. After they both received at-large
bids, Auburn was given a #1 seed, Tennessee a #2 seed.
The Data
Now that we have a general understanding of what sort of teams make
the tournament, let’s take a look at the data we’ll be using. The first,
most important dataset we have at our disposal is Ken Pomeroy’s
KenPom rankings. These are the numbers we’ll be using
to do most of our score predictions. As per the Terms of Use for this
data, here is a link to the KenPom
Website.
# We use the tidyverse and DT packages to display our data in a cleaner format as we work through it
# all. We also use the tidyverse much later in the report to create some useful graphs to draw insights
# about our data.
library(tidyverse)
library(DT)
# I initially used dplyr for some data transforming steps, but now it exists only to interact with our
# DT package,
library(dplyr)
# This was a package I found by accidentally confusing Python and R syntax, but it's incredibly useful
# for displaying the results of our prediction model that we'll be using quite a bit later.
library(glue)
# In order to point out a number of teams in the plots we'll be building to try and set apart some
# specific winners and losers, we use gghighlight to make them stand out amongst the entire field of 64
library(gghighlight)
library(cbbplotR)
# Reads in our first dataset and formats it nicely into a readable datatable
kp <- read_csv('kenpom.csv', col_names=TRUE)
data(kp, package='ggplot2')
datatable(kp,
extensions='Scroller',
options = list(scrollX=TRUE))
There’s a few variables in this data that we don’t need, so we can
safely get rid of them. The only numbers we’ll be using for now are
ORtg, DRtg, and AdjT. It may not
seem like much, but these values represent almost all we need to make
some surprisingly accurate assumptions about how these games will
go.
ORtg - A measure of opponent-adjusted offensive
efficiency, how many points a team scores per 100 possessions.
DRtg - A measure of opponent-adjusted defensive
efficiency, how many points a team allows per 100 possessions.
AdjT - A measure of opponent-adjusted “tempo,” how
many possessions a team has per 40 minutes.
# Renames some of the variables we need that shared duplicate headers with others
kp1 <- kp |>
rename(ORtg = ORtg...6, DRtg = DRtg...7)
# Removes the variables we don't need for this particular analysis
kp2 <- kp1 |>
select(-(Conf:NetRtg...5), -(Luck:NetRtg...13))
# Once again uses the DT package to display our data in a readable datatable
data(kp2, package='ggplot2')
datatable(kp2,
extensions='Scroller',
options = list(scrollX=TRUE))
Before we move on, we’re going to need a few averages from this data
to be used later as well . Each of them will be discussed later, but for
now the averages we need are:
AdjTncaa
eFGOncaa
eFGDncaa
DRtgncaa
pppncaa
eFGOncaa and eFGDncaa are two figures I
calculated separately outside of this work and have on hand, so I’ll be
assigning those values manually. They come from TeamRankings, which is
introduced below.
# Finding / assigning all of the average values we'll need later
AdjTncaa <- mean(kp2$AdjT)
eFGOncaa <- 0.5076
eFGDncaa <- 0.5096
DRtgncaa <- mean(kp2$DRtg)
pppOncaa <- mean(kp2$ORtg / 100)
Now that we have the KenPom data, we’re going to need some more
team-specific data. These are all numbers that I collected manually,
team by team, in March from the official NCAA
Statistics website and TeamRankings, and they’re
already subset to just the teams that played in the 2025 March
Madness tournament. Since we only want to look at this subset data,
we can use an inner join to get the almost complete, correctly subset
data we need containing just the 68 teams in the tournament this
year.
# Reads in our team statistics and joins it with our kenpom data so we have everything in one place
teamstats <- read_csv('team_stats.csv', )
stats <- inner_join(teamstats, kp2, by = 'team')
# Like before, displays all our data in a clean, readable, datatable
data(stats, package='ggplot2')
datatable(stats,
extensions='Scroller',
options = list(scrollX=TRUE))
Now, this is a fair amount of team statistics. Realistically we don’t
need all of it to figure out our expected winners and losers. But, we’ll
be taking a look at some of the stats we didn’t use later to figure out
if something was missing from our predictions, and how we can better
predict winners and losers in the future.
In addition to what we have already, we’re going to calculate a few
more stats that we can use. The first of these is pppO and
pppD, which are Points per Possession on both offense and
defense, respectively. This is where the KenPom data begins to
demonstrate how useful it is. The ORtg and
DRtg statistics are opponent adjusted efficiencies for both
points scored on offense and allowed on defense respectively, per-100
possessions. Therefore, we can divide those numbers by 100 to get our
pppO and pppD.
# Gives us a per-possession alternative to offensive and defensive efficiency, rather
# than per-100 possessions
stats1 <- stats |>
mutate(pppO = ORtg / 100,
pppD = DRtg / 100)
While in our expected points calculations we won’t be using these
pppO and pppD figures themselves, opting to
use the ORtg and DRtg instead, they might
prove useful when we take a look at the “upsets” after creating our
bracket simulation. We’re also going to create three more values that
may prove useful later as well. These are:
epr (Effective Possession Ratio) - The number of
shot opportunities a team has per possession.
ts (True Shooting) - Since basketball is scored in
increments of 1, 2, and 3, ts tells us the points per shot
opportunity that each team has. The constant 0.475 exists in the
calculation for this number because only about 47.5% of Free Throws
actually end a possession. Different sources have landed on different
constants to use for this figure, but KenPom uses 0.475, so I’ve elected
to stick with it as well.
ppp (Points Per Possession) - Even though we already
have our opponent-adjusted pppO for each team, this figure
gives us an objective estimate of each team’s opponent-independent
scoring prowess. In basketball, teams have the same amount of
possessions each game (+/- 1), so typically the team with the higher
ppp wins. Using epr x ts to find
ppp gives us a good estimate of each team’s scoring
ability. It essentially tells us how often a team shoots, and how many
points we expect out of each shot.
# Creates our epr, ts, and ppp variables for later use if needed
stats2 <- stats1 |>
mutate(epr = ((poss.per.game + reb.off) - to.g) / poss.per.game,
ts = scoring.off / (fga + (0.475 * fta.g)),
ppp = epr * ts)
We’ll be creating a few more variables to look at once we start to
dive into game outcomes, as well as matchup specific differences between
teams. For now these numbers give us a solid framework of what each of
the teams in the tournament brings to the table.
What Is A ‘Cinderella
Story?’
In the next sections we’ll take a look at what actually happened in
the 2025 March Madness tournament, along with what the model I
mentioned earlier predicted would happen. Before that, however, I want
to take a step back to elaborate on the title of this project. A
“Cinderella Story” team in March Madness typically refers to an
underdog, highly-seeded team that makes it much further in the
tournament than anyone expects them to. We’ve already discussed which
teams make the tournament, but the seeding process is relatively unknown
outside of the room where the NCAA Committee makes their decisions. This
is where our model deviates from the typical bracket-maker’s perception
of each game. There are over 1,000 college basketball games played
across the nation prior to March Madness, which is simply too
many for any one person to watch all of them, including those on the
committee. This is where they tend to get seeding “wrong”, as I alluded
to earlier. While one school may technically be better than another on
paper, they may not necessarily be favorites to win against a “lesser”
opponent.
Due to this seeding, even before a single game has been played in the
Round of 64 the Committee introduces a bias in favor of one team. If you
hadn’t watched a college basketball game all season, you may expect a #7
or #2 seed to defeat a #10 seed with relative ease, but this year that
wasn’t the case. For #10 Arkansas, they defied the odds in back to back
games as a true Cinderella, not favored in either game by
seeding or our model. This is the type of team we’re looking to identify
before they bust our bracket. So, with that in mind,
let’s look at the games. We’ll begin in the Round of 64.
The Model
Since all of the games have already been played, we can find the
scores on the internet and make declarations about the outcome with the
power of hindsight. But if we want to predict the outcome ahead of time,
we’re going to need to use the data we found earlier to find
opponent-adjusted expected values for each matchup. These equations are
taken directly from the blog post mentioned earlier, with some variables
adjusted to coincide with our data. We’ll start with tempo:
- Using the
AdjT values from our KenPom data, as well as
the NCAA average that we calculated earlier, we can estimate the “tempo”
of the game. This is a prediction for how many possessions each team
will have per 40 minutes. Teams that play a lower-than-average tempo
tend to control the pace of the game. They’re usually characterized by
having low shot volume, but a high make percentage, favoring quality
shots. Teams with a higher-than-average tempo are usually the opposite,
favoring a high shot volume but lower make percentages. There’s not a
“correct” way to play a game of basketball, but these different team
identities is something we’ll investigate later. The expected tempo of a
game played between Team A and Team B is:
Expected Tempo for Team A vs. B
\[\begin{align*}
E(Tempo_{A, B}) = \frac{AdjT_{A}}{AdjT_{NCAA}} *
\frac{AdjT_{B}}{AdjT_{NCAA}} * AdjT_{NCAA}
\end{align*}\]
- We can use this expected tempo value to find our next important
figure, Expected Field Goals Attempted. This will give us a measure of
how many shots Team A is expected to take, opponent-adjusted
for Team B’s defense. The equation we’ll use is:
Expected Field Goals Attempted by Team A vs. Team
B \[\begin{align*}
E(FGA_{A}) = FGA_{A} * \frac{E(Tempo_{A, B})}{AdjT_{A}}
\end{align*}\]
- Next, we’ll calculate the expected
eFG% (Effective
Field Goal Percentage). We haven’t explained eFG% yet, so
what is it? eFG% is similar to a more common measure,
FG%. FG% gives the percentage of field goals
made per field goals attempted.* eFG% is slightly more
nuanced than FG% because it accounts for both 2 and 3 point
baskets. While I didn’t explicitly calculate the eFG% values in our
dataset since they’re available in the TeamRankings data, the equation
is given below.
*This is a good opportunity to mention that in basketball, a
“field goal” is simply a shot from anywhere on the court during normal
play, i.e. not a free throw. These are not the same as the field goals
found in football.
Effective Field Goal Percentage
(eFG%) \[\begin{align*}
eFG\%\ = \frac{FG +(0.5*3P)}{FGA}
\end{align*}\]
Expected eFG% for Team A vs. Team
B \[\begin{align*}
E(eFGO)_{A} = \frac{eFGO_{A}}{eFGO_{NCAA}} *
\frac{eFGD_{B}}{eFGD_{NCAA}} * eFGO_{A} * \frac{1}{100}
\end{align*}\]
- Once we have both of those values, we’ll find the expected points
scored by Team A against Team B. We do this by
multiplying Team A’s adjusted efficiency on offense by Team
B’s adjusted efficiency as well as the expected tempo of the game
we calculated earlier, over the average NCAA defensive efficiency. Since
our efficiencies
ORtg and DRtg from the KenPom
rankings are given as points scored/allowed per-100 possessions by
nature, we end up with the expected points for each team.
Expected Points for Team A vs. Team
B \[\begin{align*}
E(Points)_{A} = \frac{ORtg_{A} * DRtg_{B} * E(Tempo_{A,B})}{DRtg_{NCAA}}
* \frac{1}{100}
\end{align*}\]
In my initial foray into this binomial distribution approach, this
was the point where I stopped. Unaware of how to effectively model the
distribution using the variance we’ll look at next, I deemed the
expected score sufficient; and to some extent it was. In 56/67 games the
team who was expected to score more points using this method, did. But
this time around we’ll look at the variance in order to add win
probabilities to our predictions.
- To calculate the variance in scoring for Team A we’ll use
the formula below. If we view field goals attempted as trials, and our
eFG% as the probability of success, we can easily find the
variance for our distribution.
Expected Variance in Scoring for Team A vs. Team
B \[\begin{align*}
Var(Points_{A}) = E(FGA_{A}) * E(eFGO_{A})(1-eFGO_{A}) * 2
\end{align*}\]
Now that we have all the equations we’ll need, we can begin to start
putting together our bracket.
Building the
Bracket
To remain within the scope of this project, I’ll refrain from
building an entire bracket simulation. Instead, opting to go game by
game and manually enter the matchups for each. But in order to do that
in a reasonable amount of time, we’re going to need to put together some
functions using the equations we just described and the averages we
calculated earlier.
# Expected Tempo for Team A vs. B
etempo <- function(teama, teamb){
(stats2[stats2$team == teama, "AdjT"] / AdjTncaa) * (stats2[stats2$team == teamb, "AdjT"] / AdjTncaa) * AdjTncaa
}
# Expected Field Goals Attempted by Team A vs. Team B
efgaa <- function(teama, teamb){
stats2[stats2$team == teama, "fga"] * (etempo(teama, teamb) / stats2[stats2$team == teama, "AdjT"])
}
# Expected Field Goals Attempted by Team B vs. Team A
efgab <- function(teama, teamb){
stats2[stats2$team == teamb, "fga"] * (etempo(teama, teamb) / stats2[stats2$team == teamb, "AdjT"])
}
# Expected eFG% for Team A vs. Team B
eefgoa <- function(teama, teamb){
(stats2[stats2$team == teama, "eFG"] / eFGOncaa) * (stats2[stats2$team == teamb, "opp.eFG"] / eFGDncaa) * stats2[stats2$team == teama, "eFG"]
}
# Expected eFG% for Team B vs. Team A
eefgob <- function(teama, teamb){
(stats2[stats2$team == teamb, "eFG"] / eFGOncaa) * (stats2[stats2$team == teama, "opp.eFG"] / eFGDncaa) * stats2[stats2$team == teamb, "eFG"]
}
# Expected Points for Team A vs. Team B
epointsa <- function(teama, teamb){
((stats2[stats2$team == teama, "ORtg"] * stats2[stats2$team == teamb, "DRtg"] * etempo(teama, teamb)) / DRtgncaa) * (1/100)
}
# Expected Points for Team B vs. Team A
epointsb <- function(teama, teamb){
((stats2[stats2$team == teamb, "ORtg"] * stats2[stats2$team == teama, "DRtg"] * etempo(teama, teamb)) / DRtgncaa) * (1/100)
}
# Expected Variance in Scoring for Team A vs. Team B, converted to a numeric value to avoid issues with the
# 'matchup' function introduced next
varpointsa <- function(teama, teamb){
vara <- efgaa(teama, teamb) * (eefgoa(teama, teamb)*(1 - eefgoa(teama, teamb))) * 2
va <- as.numeric(vara)
return(va)
}
# Expected Variance in Scoring for Team B vs. Team A
varpointsb <- function(teama, teamb){
varb <- efgab(teama, teamb) * (eefgob(teama, teamb)*(1 - eefgob(teama, teamb))) * 2
vb <- as.numeric(varb)
return(vb)
}
# This function takes the scores that we just found for Team A and Team B, and concatenates them using the "glue" package.
# We can use this function to now run through the entire tournament round by round.
matchup <- function(teama, teamb){
pa <- round(epointsa(teama, teamb), digits = 2)
pb <- round(epointsb(teama, teamb), digits = 2)
va <- varpointsa(teama, teamb)
vb <- varpointsb(teama, teamb)
# Since we know the expected score and the variance, we can use those to find win probabilities for each team
z <- (pa - pb) / sqrt(va + vb)
z <- as.numeric(z)
# Using our z score, find win percentage a and b
wpa <- round(pnorm(z), digits = 3)
wpb <- round(1 - pnorm(z), digits = 3)
# Declares the winner based on the higher win probability
if (wpa > wpb){
win <- teama
} else{
win <- teamb
}
# Calculates the expected point differential
if (pa > pb){
pd <- round(pa - pb, digits = 2)
} else{
pd <- round(pb-pa, digits = 2)
}
# Uses the "glue" package to put all of our results together into a nice output and prints it afterwards.
out <- glue("{teama} Expected score: {pa},
{teamb} Expected score: {pb},
Projected Point Differential: {pd}
Win Probability for {teama}: {wpa}
Win Probability for {teamb}: {wpb}
Projected winner: {win}")
out
}
Now that we have our functions, we can easily run through each
matchup and reduce 67 basketball games to a few function calls.
Our Predictions
Round of 64
The South Region
matchup("Auburn", "Alabama St.")
## Auburn Expected score: 90.66,
## Alabama St. Expected score: 60.35,
## Projected Point Differential: 30.31
## Win Probability for Auburn: 1
## Win Probability for Alabama St.: 0
## Projected winner: Auburn
matchup("Louisville", "Creighton")
## Louisville Expected score: 74.52,
## Creighton Expected score: 71.66,
## Projected Point Differential: 2.86
## Win Probability for Louisville: 0.647
## Win Probability for Creighton: 0.353
## Projected winner: Louisville
matchup("Michigan", "UC San Diego")
## Michigan Expected score: 71.22,
## UC San Diego Expected score: 68.49,
## Projected Point Differential: 2.73
## Win Probability for Michigan: 0.641
## Win Probability for UC San Diego: 0.359
## Projected winner: Michigan
matchup("Texas A&M", "Yale")
## Texas A&M Expected score: 74.9,
## Yale Expected score: 65.64,
## Projected Point Differential: 9.26
## Win Probability for Texas A&M: 0.886
## Win Probability for Yale: 0.114
## Projected winner: Texas A&M
matchup("Ole Miss", "North Carolina")
## Ole Miss Expected score: 78.16,
## North Carolina Expected score: 76.61,
## Projected Point Differential: 1.55
## Win Probability for Ole Miss: 0.578
## Win Probability for North Carolina: 0.422
## Projected winner: Ole Miss
matchup("Iowa St.", "Lipscomb")
## Iowa St. Expected score: 77.65,
## Lipscomb Expected score: 65.62,
## Projected Point Differential: 12.03
## Win Probability for Iowa St.: 0.946
## Win Probability for Lipscomb: 0.054
## Projected winner: Iowa St.
matchup("Marquette", "New Mexico")
## Marquette Expected score: 76.78,
## New Mexico Expected score: 73.93,
## Projected Point Differential: 2.85
## Win Probability for Marquette: 0.638
## Win Probability for New Mexico: 0.362
## Projected winner: Marquette
matchup("Michigan St.", "Bryant")
## Michigan St. Expected score: 85.4,
## Bryant Expected score: 66.07,
## Projected Point Differential: 19.33
## Win Probability for Michigan St.: 0.992
## Win Probability for Bryant: 0.008
## Projected winner: Michigan St.
The West Region
matchup("Florida", "Norfolk St.")
## Florida Expected score: 89.92,
## Norfolk St. Expected score: 63.71,
## Projected Point Differential: 26.21
## Win Probability for Florida: 1
## Win Probability for Norfolk St.: 0
## Projected winner: Florida
matchup("UConn", "Oklahoma")
## UConn Expected score: 74.66,
## Oklahoma Expected score: 74.32,
## Projected Point Differential: 0.34
## Win Probability for UConn: 0.518
## Win Probability for Oklahoma: 0.482
## Projected winner: UConn
matchup("Memphis", "Colorado St.")
## Memphis Expected score: 73.01,
## Colorado St. Expected score: 73.82,
## Projected Point Differential: 0.81
## Win Probability for Memphis: 0.457
## Win Probability for Colorado St.: 0.543
## Projected winner: Colorado St.
matchup("Maryland", "Grand Canyon")
## Maryland Expected score: 82.54,
## Grand Canyon Expected score: 68.75,
## Projected Point Differential: 13.79
## Win Probability for Maryland: 0.959
## Win Probability for Grand Canyon: 0.041
## Projected winner: Maryland
matchup("Missouri", "Drake")
## Missouri Expected score: 68.99,
## Drake Expected score: 63.45,
## Projected Point Differential: 5.54
## Win Probability for Missouri: 0.788
## Win Probability for Drake: 0.212
## Projected winner: Missouri
matchup("Texas Tech", "UNCW")
## Texas Tech Expected score: 79.89,
## UNCW Expected score: 64.98,
## Projected Point Differential: 14.91
## Win Probability for Texas Tech: 0.977
## Win Probability for UNCW: 0.023
## Projected winner: Texas Tech
matchup("Kansas", "Arkansas")
## Kansas Expected score: 72.97,
## Arkansas Expected score: 69.21,
## Projected Point Differential: 3.76
## Win Probability for Kansas: 0.684
## Win Probability for Arkansas: 0.316
## Projected winner: Kansas
matchup("St. John's (NY)", "Omaha")
## St. John's (NY) Expected score: 83.34,
## Omaha Expected score: 64.32,
## Projected Point Differential: 19.02
## Win Probability for St. John's (NY): 0.992
## Win Probability for Omaha: 0.008
## Projected winner: St. John's (NY)
The East Region
matchup("Duke", "Mount St. Mary's")
## Duke Expected score: 84.46,
## Mount St. Mary's Expected score: 55.42,
## Projected Point Differential: 29.04
## Win Probability for Duke: 1
## Win Probability for Mount St. Mary's: 0
## Projected winner: Duke
matchup("Mississippi St.", "Baylor")
## Mississippi St. Expected score: 72.52,
## Baylor Expected score: 72.93,
## Projected Point Differential: 0.41
## Win Probability for Mississippi St.: 0.479
## Win Probability for Baylor: 0.521
## Projected winner: Baylor
matchup("Oregon", "Liberty")
## Oregon Expected score: 70.89,
## Liberty Expected score: 66.86,
## Projected Point Differential: 4.03
## Win Probability for Oregon: 0.71
## Win Probability for Liberty: 0.29
## Projected winner: Oregon
matchup("Arizona", "Akron")
## Arizona Expected score: 91.26,
## Akron Expected score: 76.7,
## Projected Point Differential: 14.56
## Win Probability for Arizona: 0.965
## Win Probability for Akron: 0.035
## Projected winner: Arizona
matchup("BYU", "VCU")
## BYU Expected score: 73.04,
## VCU Expected score: 72.32,
## Projected Point Differential: 0.72
## Win Probability for BYU: 0.538
## Win Probability for VCU: 0.462
## Projected winner: BYU
matchup("Wisconsin", "Montana")
## Wisconsin Expected score: 85.11,
## Montana Expected score: 67.09,
## Projected Point Differential: 18.02
## Win Probability for Wisconsin: 0.993
## Win Probability for Montana: 0.007
## Projected winner: Wisconsin
matchup("Saint Mary's (CA)", "Vanderbilt")
## Saint Mary's (CA) Expected score: 70.16,
## Vanderbilt Expected score: 65.03,
## Projected Point Differential: 5.13
## Win Probability for Saint Mary's (CA): 0.748
## Win Probability for Vanderbilt: 0.252
## Projected winner: Saint Mary's (CA)
matchup("Alabama", "Robert Morris")
## Alabama Expected score: 93.81,
## Robert Morris Expected score: 72.99,
## Projected Point Differential: 20.82
## Win Probability for Alabama: 0.996
## Win Probability for Robert Morris: 0.004
## Projected winner: Alabama
The Midwest Region
matchup("Houston", "SIU Edwardsville")
## Houston Expected score: 73.68,
## SIU Edwardsville Expected score: 50.39,
## Projected Point Differential: 23.29
## Win Probability for Houston: 0.999
## Win Probability for SIU Edwardsville: 0.001
## Projected winner: Houston
matchup("Gonzaga", "Georgia")
## Gonzaga Expected score: 77.03,
## Georgia Expected score: 72.21,
## Projected Point Differential: 4.82
## Win Probability for Gonzaga: 0.732
## Win Probability for Georgia: 0.268
## Projected winner: Gonzaga
matchup("Clemson", "McNeese")
## Clemson Expected score: 69.93,
## McNeese Expected score: 63.45,
## Projected Point Differential: 6.48
## Win Probability for Clemson: 0.808
## Win Probability for McNeese: 0.192
## Projected winner: Clemson
matchup("Purdue", "High Point")
## Purdue Expected score: 81.59,
## High Point Expected score: 71.58,
## Projected Point Differential: 10.01
## Win Probability for Purdue: 0.917
## Win Probability for High Point: 0.083
## Projected winner: Purdue
matchup("Illinois", "Xavier")
## Illinois Expected score: 82.16,
## Xavier Expected score: 77.81,
## Projected Point Differential: 4.35
## Win Probability for Illinois: 0.709
## Win Probability for Xavier: 0.291
## Projected winner: Illinois
matchup("Kentucky", "Troy")
## Kentucky Expected score: 81.61,
## Troy Expected score: 70.28,
## Projected Point Differential: 11.33
## Win Probability for Kentucky: 0.929
## Win Probability for Troy: 0.071
## Projected winner: Kentucky
matchup("UCLA", "Utah St.")
## UCLA Expected score: 75.45,
## Utah St. Expected score: 70.04,
## Projected Point Differential: 5.41
## Win Probability for UCLA: 0.768
## Win Probability for Utah St.: 0.232
## Projected winner: UCLA
matchup("Tennessee", "Wofford")
## Tennessee Expected score: 74.67,
## Wofford Expected score: 57.48,
## Projected Point Differential: 17.19
## Win Probability for Tennessee: 0.99
## Win Probability for Wofford: 0.01
## Projected winner: Tennessee
Results
So, how did we do? Not good enough, if 67/67 is our eventual goal.
But let’s take a look at what games we got wrong and keep a running
tally in the Results tab so that we can take a look at those
teams afterwards.
The games we got wrong and their respective Win Probabilities:
#8 Louisville (64.7%) vs #9
Creighton (35.3%)
#7 Marquette (63.8%) vs #10 New
Mexico (36.2%)
#6 Missouri (78.8%) vs #11
Drake (21.2%)
#7 Kansas (68.4%) vs #10
Arkansas (31.6%)
#5 Clemson (80.8%) vs #12
McNeese (19.2%)
Round of 32
The South Region
matchup("Auburn", "Creighton")
## Auburn Expected score: 79.67,
## Creighton Expected score: 68.86,
## Projected Point Differential: 10.81
## Win Probability for Auburn: 0.921
## Win Probability for Creighton: 0.079
## Projected winner: Auburn
matchup("Michigan", "Texas A&M")
## Michigan Expected score: 68.32,
## Texas A&M Expected score: 69.62,
## Projected Point Differential: 1.3
## Win Probability for Michigan: 0.432
## Win Probability for Texas A&M: 0.568
## Projected winner: Texas A&M
matchup("Ole Miss", "Iowa St.")
## Ole Miss Expected score: 70.84,
## Iowa St. Expected score: 74.3,
## Projected Point Differential: 3.46
## Win Probability for Ole Miss: 0.327
## Win Probability for Iowa St.: 0.673
## Projected winner: Iowa St.
matchup("New Mexico", "Michigan St.")
## New Mexico Expected score: 69.73,
## Michigan St. Expected score: 77.28,
## Projected Point Differential: 7.55
## Win Probability for New Mexico: 0.172
## Win Probability for Michigan St.: 0.828
## Projected winner: Michigan St.
The West Region
matchup("Florida", "UConn")
## Florida Expected score: 81.54,
## UConn Expected score: 69.61,
## Projected Point Differential: 11.93
## Win Probability for Florida: 0.94
## Win Probability for UConn: 0.06
## Projected winner: Florida
matchup("Colorado St.", "Maryland")
## Colorado St. Expected score: 68.38,
## Maryland Expected score: 75.16,
## Projected Point Differential: 6.78
## Win Probability for Colorado St.: 0.187
## Win Probability for Maryland: 0.813
## Projected winner: Maryland
matchup("Drake", "Texas Tech")
## Drake Expected score: 58.67,
## Texas Tech Expected score: 66.16,
## Projected Point Differential: 7.49
## Win Probability for Drake: 0.142
## Win Probability for Texas Tech: 0.858
## Projected winner: Texas Tech
matchup("Arkansas", "St. John's (NY)")
## Arkansas Expected score: 67.03,
## St. John's (NY) Expected score: 73.43,
## Projected Point Differential: 6.4
## Win Probability for Arkansas: 0.212
## Win Probability for St. John's (NY): 0.788
## Projected winner: St. John's (NY)
The East Region
matchup("Duke", "Baylor")
## Duke Expected score: 75.38,
## Baylor Expected score: 64.01,
## Projected Point Differential: 11.37
## Win Probability for Duke: 0.938
## Win Probability for Baylor: 0.062
## Projected winner: Duke
matchup("Oregon", "Arizona")
## Oregon Expected score: 74.34,
## Arizona Expected score: 77.93,
## Projected Point Differential: 3.59
## Win Probability for Oregon: 0.323
## Win Probability for Arizona: 0.677
## Projected winner: Arizona
matchup("BYU", "Wisconsin")
## BYU Expected score: 74.77,
## Wisconsin Expected score: 77.72,
## Projected Point Differential: 2.95
## Win Probability for BYU: 0.349
## Win Probability for Wisconsin: 0.651
## Projected winner: Wisconsin
matchup("Saint Mary's (CA)", "Alabama")
## Saint Mary's (CA) Expected score: 71.58,
## Alabama Expected score: 75.03,
## Projected Point Differential: 3.45
## Win Probability for Saint Mary's (CA): 0.331
## Win Probability for Alabama: 0.669
## Projected winner: Alabama
The Midwest Region
matchup("Houston", "Gonzaga")
## Houston Expected score: 71.28,
## Gonzaga Expected score: 65.15,
## Projected Point Differential: 6.13
## Win Probability for Houston: 0.786
## Win Probability for Gonzaga: 0.214
## Projected winner: Houston
matchup("McNeese", "Purdue")
## McNeese Expected score: 68,
## Purdue Expected score: 74.02,
## Projected Point Differential: 6.02
## Win Probability for McNeese: 0.205
## Win Probability for Purdue: 0.795
## Projected winner: Purdue
matchup("Illinois", "Kentucky")
## Illinois Expected score: 85.33,
## Kentucky Expected score: 85.58,
## Projected Point Differential: 0.25
## Win Probability for Illinois: 0.488
## Win Probability for Kentucky: 0.512
## Projected winner: Kentucky
matchup("UCLA", "Tennessee")
## UCLA Expected score: 59.93,
## Tennessee Expected score: 65.83,
## Projected Point Differential: 5.9
## Win Probability for UCLA: 0.212
## Win Probability for Tennessee: 0.788
## Projected winner: Tennessee
Results
The games we got wrong and their respective Win Probabilities:
#5 Michigan (43.2%) vs #4 Texas
A&M (56.8%)
#6 Ole Miss (32.7%) vs #3 Iowa
St. (67.3%)
#10 Arkansas (21.2%) vs #2
St. John’s (78.8%)
#6 BYU (34.9%) vs #3 Wisconsin
(65.1%)
Sweet Sixteen
The South Region
matchup("Auburn", "Michigan")
## Auburn Expected score: 78.74,
## Michigan Expected score: 70.78,
## Projected Point Differential: 7.96
## Win Probability for Auburn: 0.847
## Win Probability for Michigan: 0.153
## Projected winner: Auburn
matchup("Ole Miss", "Michigan St.")
## Ole Miss Expected score: 68.47,
## Michigan St. Expected score: 72.59,
## Projected Point Differential: 4.12
## Win Probability for Ole Miss: 0.298
## Win Probability for Michigan St.: 0.702
## Projected winner: Michigan St.
The West Region
matchup("Florida", "Maryland")
## Florida Expected score: 79.95,
## Maryland Expected score: 73.9,
## Projected Point Differential: 6.05
## Win Probability for Florida: 0.774
## Win Probability for Maryland: 0.226
## Projected winner: Florida
matchup("Texas Tech", "Arkansas")
## Texas Tech Expected score: 75.36,
## Arkansas Expected score: 69.39,
## Projected Point Differential: 5.97
## Win Probability for Texas Tech: 0.782
## Win Probability for Arkansas: 0.218
## Projected winner: Texas Tech
The East Region
matchup("Duke", "Arizona")
## Duke Expected score: 79.32,
## Arizona Expected score: 70.4,
## Projected Point Differential: 8.92
## Win Probability for Duke: 0.878
## Win Probability for Arizona: 0.122
## Projected winner: Duke
matchup("BYU", "Alabama")
## BYU Expected score: 83.17,
## Alabama Expected score: 89.17,
## Projected Point Differential: 6
## Win Probability for BYU: 0.223
## Win Probability for Alabama: 0.777
## Projected winner: Alabama
The Midwest Region
matchup("Houston", "Purdue")
## Houston Expected score: 68.81,
## Purdue Expected score: 60.71,
## Projected Point Differential: 8.1
## Win Probability for Houston: 0.866
## Win Probability for Purdue: 0.134
## Projected winner: Houston
matchup("Kentucky", "Tennessee")
## Kentucky Expected score: 69.33,
## Tennessee Expected score: 75.24,
## Projected Point Differential: 5.91
## Win Probability for Kentucky: 0.22
## Win Probability for Tennessee: 0.78
## Projected winner: Tennessee
Results
The games we got wrong and their respective Win Probabilities:
Elite Eight
The South Region
matchup("Auburn", "Michigan St.")
## Auburn Expected score: 74.19,
## Michigan St. Expected score: 70.35,
## Projected Point Differential: 3.84
## Win Probability for Auburn: 0.689
## Win Probability for Michigan St.: 0.311
## Projected winner: Auburn
The West Region
matchup("Florida", "Texas Tech")
## Florida Expected score: 79.31,
## Texas Tech Expected score: 73.46,
## Projected Point Differential: 5.85
## Win Probability for Florida: 0.772
## Win Probability for Texas Tech: 0.228
## Projected winner: Florida
The East Region
matchup("Duke", "Alabama")
## Duke Expected score: 84.62,
## Alabama Expected score: 77.73,
## Projected Point Differential: 6.89
## Win Probability for Duke: 0.808
## Win Probability for Alabama: 0.192
## Projected winner: Duke
The Midwest Region
matchup("Houston", "Tennessee")
## Houston Expected score: 59.75,
## Tennessee Expected score: 57.49,
## Projected Point Differential: 2.26
## Win Probability for Houston: 0.621
## Win Probability for Tennessee: 0.379
## Projected winner: Houston
Results
The games we got wrong and their respective Win Probabilities:
Final Four
South/West
matchup("Auburn", "Florida")
## Auburn Expected score: 77.87,
## Florida Expected score: 78.69,
## Projected Point Differential: 0.82
## Win Probability for Auburn: 0.459
## Win Probability for Florida: 0.541
## Projected winner: Florida
East/Midwest
matchup("Duke", "Houston")
## Duke Expected score: 63.19,
## Houston Expected score: 62.14,
## Projected Point Differential: 1.05
## Win Probability for Duke: 0.556
## Win Probability for Houston: 0.444
## Projected winner: Duke
Results
The game we got wrong and its respective Win Probability:
- #1 Duke (55.6%) vs #1 Houston
(44.4%)
National Championship
You may have noticed by now that each round, I am replacing the
results that we predicted with the real-life outcomes. Up to this point
it wouldn’t have made a difference outside of one game,
#10 Arkansas vs #2 St. John’s. Every
other team we incorrectly guessed would lose, besides Arkansas, went on
to lose in the next round and didn’t change the outcome of the Sweet
Sixteen and Elite Eight. Houston, ironically, is not an exception to
this rule, despite our prediction giving them a slight edge in this
final, incorrect, result. In reality, Florida defeated Houston 65-63 to
claim the National Title.
If this were next year’s bracket and we didn’t know all of the
outcomes yet, incorrectly guessing the winner of both a Final Four game
and the Championship would be an incredibly poor way to lose a
perfect bracket. But this highlights a concept that I’ll touch on later
despite not fully understanding. As the field narrows and the level of
play increases, our predictions, in theory, should be worse.
matchup("Florida", "Houston")
## Florida Expected score: 67.26,
## Houston Expected score: 67.81,
## Projected Point Differential: 0.55
## Win Probability for Florida: 0.472
## Win Probability for Houston: 0.528
## Projected winner: Houston
The game we got wrong and its respective Win Probability:
- #1 Florida (47.2%) vs #1 Houston
(52.8%)
The Results
Before we get into graphing these teams and trying to come up with
some clues that may have prevented our bracket from busting on the very
first game of the Round of 64 (Louisville vs Creighton), let’s just take
a look at all of the matchups we got incorrectly in one place. Of my
56/67 results, here are all 11 incorrect predictions.
Round of 64
#8 Louisville (64.7%) vs #9
Creighton (35.3%)
#7 Marquette (63.8%) vs #10 New
Mexico (36.2%)
#6 Missouri (78.8%) vs #11
Drake (21.2%)
#7 Kansas (68.4%) vs #10
Arkansas (31.6%)
#5 Clemson (80.8%) vs #12
McNeese (19.2%)
Round of 32
#5 Michigan (43.2%) vs #4 Texas
A&M (56.8%)
#6 Ole Miss (32.7%) vs #3 Iowa
St. (67.3%)
#10 Arkansas (21.2%) vs #2
St. John’s (78.8%)
#6 BYU (34.9%) vs #3 Wisconsin
(65.1%)
Final Four
- #1 Duke (55.6%) vs #1 Houston
(44.4%)
National Championship
- #1 Florida (47.2%) vs #1 Houston
(52.8%)
We can see that as we get closer to the Championship, and then in the
Championship itself, the level of competition gets much more even. Our
win probabilities amount to essentially a coin flip, especially when
considering that the scores of each game after the Elite Eight
is predicted to be within 1 point. None of the games actually ended in
such a narrow margin, but both of the games that we predicted
incorrectly were decided by one possession. The only game we
got correct (Auburn vs Florida) was decided by 6 points, or just two
possessions.
Getting all of the Sweet Sixteen and Elite Eight games correct as the
competition narrows is a result I’m content with, but doesn’t serve us
too much useful information. In fact, out of all twelve games played in
those rounds that we got correct, only three of them ended within one
possession. Realistically, there’s an element of luck when it comes to
deciding which team will win these coin flip games if we go strictly by
the score predictions, and not some other metric.
On the other end of the spectrum, are the true upsets - the
beginnings of a Cinderella Story. While 2025’s bracket featured
relatively little chaos, there are two teams that stand out from the
crowd in our group of incorrect predictions above. The first, who has
been mentioned on more than one occasion already, the Arkansas
Razorbacks. The only double-digit seed to make it to the Sweet
Sixteen with relatively modest, but respectable stats, the Razorbacks
weren’t necessarily a prototypical Cinderella team. By virtue of playing
in the SEC, which many considered to be the strongest conference in the
nation last year, they carried a lot more talent than their seeding
might suggest. However, we were still unable to predict either of their
upset wins correctly.
The other notable team, owners of the largest upset victory
throughout the entire tournament - the McNeese Cowboys.
This result hits particularly close to home, as it came at the
consequence of an early exit for my own Clemson Tigers. I will refrain
from making any biased comments or assumptions about the outcome of that
game that can’t be verified by the data I have in front of me, and will
instead opt to credit the unexpected loss to an injury suffered by
Clemson guard Dillon Hunter during the ACC Tournament.
The rest of the incorrect guesses tend to fall in the range of around
a 30-45% win probability percentage for the underdogs. These are results
that likely could have gone either way, but without investigating them
further we’re left victims of chance. In order to try and garner some
insight, I’ll explore some of the statistics we have at our disposal to
see if there’s a discrepancy between our “Cinderellas” and our
proverbial “stepsisters.”
The Glass Slipper -
What Sets Teams Apart?
We’ll first start by creating a subset of the teams that pulled off
an “upset” given our predictions, and a separate subset of the teams who
lost to them. That way, we can highlight each and see if there’s any
significant differences between the two groups.
# Filters out just our "underdogs"
unders <- stats2 |>
filter(team %in% c("Creighton", "New Mexico", "Drake", "Arkansas", "McNeese", "Michigan", "Ole Miss", "BYU", "Houston", "Florida"))
# Filters out just the teams our "underdogs" lost to
upsets <- stats2 |>
filter(team %in% c("Louisville", "Marquette", "Missouri", "Kansas", "Clemson", "Texas A&M", "Iowa St.", "St. John's (NY)", "Wisconsin", "Duke", "Houston"))
ggplot(stats2, aes(x = eFG, y = opp.eFG))+
geom_vline(xintercept = mean(stats2$eFG), color = "black")+
geom_hline(yintercept = mean(stats2$opp.eFG), color = "black")+
geom_cbb_teams(data = stats2, aes(team = team), width = 0.05, show.legend = FALSE)+
gghighlight(team %in% c("Creighton", "New Mexico", "Drake", "Arkansas", "McNeese", "Michigan", "Ole Miss", "BYU", "Houston", "Florida"))+
xlim(min(stats2$eFG), max(stats2$eFG))+
ylim(min(stats2$opp.eFG), max(stats2$opp.eFG))+
labs(x = "Team eFG%",
y = "Opponent eFG%",
title = 'Team eFG% vs. Opponent eFG% for "Underdog" Teams')
ggplot(stats2, aes(x = eFG, y = opp.eFG))+
geom_vline(xintercept = mean(stats2$eFG), color = "black")+
geom_hline(yintercept = mean(stats2$opp.eFG), color = "black")+
geom_cbb_teams(data = stats2, aes(team = team), width=0.05, show.legend = FALSE)+
gghighlight(team %in% c("Louisville", "Marquette", "Missouri", "Kansas", "Clemson", "Texas A&M", "Iowa St.", "St. John's (NY)", "Wisconsin", "Duke", "Houston"))+
xlim(min(stats2$eFG), max(stats2$eFG))+
ylim(min(stats2$opp.eFG), max(stats2$opp.eFG))+
labs(x = "Team eFG%",
y = "Opponent eFG%",
title = 'Team eFG% vs. Opponent eFG% for Teams Who Were "Upset"')


Here we get some slight insight as to the difference between a few of
these teams, but for the most part the results are inconclusive. In this
particular graph, you want to be in the bottom right quadrant with a
high eFG%, and a low opp.eFG%. We can see that
teams like McNeese, Creighton, and
Michigan fare better in both eFG% and
opp.eFG% than their opponents, but more often than not the
pattern doesn’t seem to hold. It’s still worth noting that six of the
teams who suffered upset losses had a below average eFG%,
and Clemson is just sightly above average.
Since eFG% and opp.eFG% aren’t
opponent-adjusted, we can try to compare our opponent-adjusted
efficiencies and see if that gives us some more insight. Even though
this follows our methodology for finding our expected scores, and likely
won’t tell us much, one or two outliers could be the difference maker
when deciding which otherwise evenly-matched team we should pick.
ggplot(stats2, aes(x = ORtg, y = DRtg))+
geom_vline(xintercept = mean(stats2$ORtg), color = "black")+
geom_hline(yintercept = mean(stats2$DRtg), color = "black")+
geom_cbb_teams(data = stats2, aes(team = team), width=0.05, show.legend = FALSE)+
gghighlight(team %in% c("Creighton", "New Mexico", "Drake", "Arkansas", "McNeese", "Michigan", "Ole Miss", "BYU", "Houston", "Florida"))+
xlim(min(stats2$ORtg), max(stats2$ORtg))+
ylim(min(stats2$DRtg), max(stats2$DRtg))+
labs(x = "Team ORtg",
y = "Team DRtg",
title = 'Team ORtg vs. Team DRtg for "Underdog" Teams')
ggplot(stats2, aes(x = ORtg, y = DRtg))+
geom_vline(xintercept = mean(stats2$ORtg), color = "black")+
geom_hline(yintercept = mean(stats2$DRtg), color = "black")+
geom_cbb_teams(data = stats2, aes(team = team), width=0.05, show.legend = FALSE)+
gghighlight(team %in% c("Louisville", "Marquette", "Missouri", "Kansas", "Clemson", "Texas A&M", "Iowa St.", "St. John's (NY)", "Wisconsin", "Duke", "Houston"))+
xlim(min(stats2$ORtg), max(stats2$ORtg))+
ylim(min(stats2$DRtg), max(stats2$DRtg))+
labs(x = "Team ORtg",
y = "Team DRtg",
title = 'Team ORtg vs. Team DRtg for Teams Who Were "Upset"')


As expected, this graph doesn’t tell us all too much either. The only
real insight here might be that given the clustering of the teams who
faced upsets, the ones who lost in the Round of 64 and Round of 32 don’t
do anything exceptionally well. They’re above average in offensive and
defensive efficiency, but they aren’t immune to losing a basketball
game. The other teams all the way out on the right end of the graph with
Duke in ORtg are Florida, who would eventually go on to win
the Tournament, and Auburn, who lost to Florida in the Final Four.
The team closest to Houston on this graph? Tennessee. Who they
defeated in the Elite Eight. I think it’s not unreasonable to say that
these teams are somewhat immune to upsets, all the way
down in the bottom right of the graph. Teams like St. John’s and
Missouri though, who excel on one end of the court and are relatively
pedestrian on the other, don’t share that luxury.
We’ve determined that scoring efficiency matters to some extent, as
does the amount each team scores per shot. Let’s take those concepts
now, and look to see if these teams fit into either of the “team
identities” we mentioned earlier. Across the sport of basketball, the
three-pointer has completely reshaped the scoring landscape. Perhaps we
can see if there’s a discrepancy between the slower, more methodical
teams who try to craft the perfect shot, and the more “run and gun”
style of play.
ggplot(stats2, aes(x = AdjT, y = threep.perc.off))+
geom_vline(xintercept = mean(stats2$AdjT), color = "black")+
geom_hline(yintercept = mean(stats2$threep.perc.off), color = "black")+
geom_cbb_teams(data = stats2, aes(team = team), width=0.05, show.legend = FALSE)+
gghighlight(team %in% c("Creighton", "New Mexico", "Drake", "Arkansas", "McNeese", "Michigan", "Ole Miss", "BYU", "Houston", "Florida"))+
xlim(min(stats2$AdjT), max(stats2$AdjT))+
ylim(min(stats2$threep.perc.off), max(stats2$threep.perc.off))+
labs(x = "Team AdjT",
y = "Team 3P%",
title = 'Team AdjT vs. Team 3P% for "Underdog" Teams')
ggplot(stats2, aes(x = AdjT, y = threep.perc.off))+
geom_vline(xintercept = mean(stats2$AdjT), color = "black")+
geom_hline(yintercept = mean(stats2$threep.perc.off), color = "black")+
geom_cbb_teams(data = stats2, aes(team = team), width=0.05, show.legend = FALSE)+
gghighlight(team %in% c("Louisville", "Marquette", "Missouri", "Kansas", "Clemson", "Texas A&M", "Iowa St.", "St. John's (NY)", "Wisconsin", "Duke", "Houston"))+
xlim(min(stats2$AdjT), max(stats2$AdjT))+
ylim(min(stats2$threep.perc.off), max(stats2$threep.perc.off))+
labs(x = "Team AdjT",
y = "Team 3P%",
title = 'Team AdjT vs. Team 3P% for Teams Who Were "Upset"')


Right off the bat, this graph gives us an excellent look at a couple
matchup-specific differences between teams. We can see a few clear
trends right away, that seem to hold with our earlier assumptions. The
first of these is that high-tempo teams struggle against low tempo
teams. This was a concept I generally grasped and had brought up
already, but now we can see clearly just how big of an impact it can
have. #11 Drake plays at an absolutely glacial pace, averaging just 58.8
possessions per game. They’re the slowest team in the country, and that
change of pace was enough for them to topple a fast Missouri team who
couldn’t adjust to essentially walking up and down the court.
Unfortunately for Drake, they ran into Texas Tech in the Round of 32
(the point on the graph right above Duke). Texas Tech is comfortable
playing at a slower than average tempo, and shoots much more efficiently
than Drake, at a higher volume. For teams that play at a similar tempo,
within 2-3 possessions per game, the more efficient teams almost always
win.
There are only three exceptions to this rule in our plot, one of
which we already deemed a coin flip earlier in #1 Houston vs #1 Florida.
Coincidentally, those two exceptions are our “Cinderella” teams.
Or so it may seem. Along with Clemson, who was without
Dillon Hunter in their first and only game in the tournament, Kansas was
also playing shorthanded. Briefly. Leading 67-64 over Arkansas with 3:10
on the clock, Jayhawks’ star forward KJ Adams tore his achilles and was
forced to leave the game. In the remaining 3 minutes and 10 seconds
Arkansas would go on to outscore Kansas 15-5, closing out the game with
a final score of 79-72 in favor of the Razorbacks. Outside of those two
injury-related anomalies, and the National Championship game, our rule
holds across all the other upsets. When two otherwise evenly-matched
teams square off against each other, the team that’s more efficient from
behind the arc is almost always going to win.
You can investigate all of this for yourself using the flexdashboard
I’ve created for this data as well.
Takeaways
Our win probabilities give us a good idea of clear winners. Any team
with a 70% chance to win or better won in all but three instances. Two
of these we can attribute to injuries adding an element of randomness,
and the third we can attribute to a vast difference between the
two teams’ shooting ability, which is just part of the Rick Pitino
Experience. Any team with a 30% chance to win or better, can win. We can
almost perfectly predict the outcome in these games based on two things.
The first is tempo, much slower teams hold an advantage over teams that
like to play faster than average. The second, when tempo is not a
question, is 3P%. Teams that are able to score threes at a
higher clip than their opponent almost always walk away with a victory
over less-efficient shooting. Our notable exception to this is the
National Championship game, where the best offense in the country faced
off against the (second) best defense in the country. These teams at the
very top of our offensive and defensive rankings seem to be juggernauts
when moving through bracket, and until they meet an opponent with
similar ability, they’re going to easily make their way towards the
later rounds.
It’s impossible to predict injuries. No model can account for that
event in the middle of the tournament. But that’s the beauty of solving
the March Madness bracket. Simply put, nobody knows what’s
going to happen and there’s an element of randomness that comes with
making picks. Some may even call it luck. I posit that if we were to
look at every individual matchup and apply only the rules comparing
3P% to AdjT in cases where closely matched
teams play at a similar speed, and favoring the slower team if they
don’t, our bracket would put up some reasonably successful results.
Regardless of the inherent randomness that comes with any live
sporting event, we can definitely draw a lot more insights from this
approach than I began with. By applying this concept of “team
identities,” rather than blindly following a score prediction, I
wouldn’t be surprised if this model, when applied with a new, deeper
understanding of team matchups, sees upwards of 60/67 correct picks.
There’s 40 different variables - some more important than others - in
this dataset. I could sit here for the next few months of my life
investigating each, building a regression model with all 40 and trying
to fit it perfectly. At the end of the day, nothing’s going to account
for the randomness. In fact, among my friend group, despite being
correct on 56/67 picks compared to our winner who achieved a solid
51/67, if I had used only the score predictions of this particular model
I would’ve come in just sixth place out of the sixteen of us in our
“bracket pool.” There, the scoring favors the Final Four and
Championship much more heavily than the earlier rounds. Of the five who
would’ve been ahead of me, three of them had a Final Four of all the #1
seeds. An event that prior to this year had only occurred once in the
history of March Madness, was seemingly likely enough for all
three to pick it. On top of that, six out of the sixteen had Florida
winning it all, but there’s randomness in that
normalcy. Perhaps it’s an indication that the selection
committee is getting much better with their seeding, and the chaos will
start to vanish from the tournament? Maybe NIL is to blame, and college
basketball is doomed to see these more dominant teams run the tournament
each year. Who knows? I certainly don’t, but I’ll still be right here
making my picks in March along with millions of others.
About Me
I am a first year graduate student pursuing my master’s degree in
Data Science and Analytics at Clemson University. As the middle of seven
children who all pursued different activities growing up outside of
Philadelphia, sports have always been a focal point in my life. Applying
statistics to sports opened my eyes to the power of data, and brought me
to where I am today. The March Madness bracket in particular is
a challenge that I would love to continue to take on in order to build
my tool set as I dive deeper into this field. Some of the best and
brightest have contributed their minds to predicting the outcome of this
tournament, and none have succeeded so far. Problems like this are what
drives my passion for learning, and I hope to continue to both find and
solve these problems as I move towards earning my degree and out into
the world.
LS0tDQp0aXRsZTogIkZpbmRpbmcgQ2luZGVyZWxsYSINCmF1dGhvcjogIkNhZWxhbiBDb3luZSINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAyDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgdGhlbWU6IGZsYXRseQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCi0tLQ0KDQo8Y2VudGVyPg0KIVtdKE1hcmNoX01hZG5lc3NfbG9nby5wbmcpDQo8L2NlbnRlcg0KDQo8YnI+DQoNCn4qSW1hZ2UgY291cnRlc3kgb2YgdGhlIE5DQUEqfg0KDQojIEludHJvZHVjdGlvbg0KDQpUaGlzIHByb2plY3Qgd2lsbCBidWlsZCBvbiBvbmUgdGhhdCBJIGJlZ2FuIGluIE1hcmNoIG9mIDIwMjUsIHByZWRpY3RpbmcgdGhlIG91dGNvbWVzIG9mICpNYXJjaCBNYWRuZXNzKiB0b3VybmFtZW50IGdhbWVzLiAqTWFyY2ggTWFkbmVzcyogaXMgYSBzaW5nbGUtZWxpbWluYXRpb24gYmFza2V0YmFsbCB0b3VybmFtZW50IGZlYXR1cmluZyA2OCB0ZWFtcywgd2l0aCByZXByZXNlbnRhdGl2ZXMgZnJvbSBldmVyeSBjb25mZXJlbmNlIGluIERpdmlzaW9uIEkgTkNBQSBiYXNrZXRiYWxsLiBUaGUgNjgtdGVhbSBwb29sIGlzIG5hcnJvd2VkIGRvd24gdG8gNjQgYWZ0ZXIgZWlnaHQgdGVhbXMgcGxheSBlYWNoIG90aGVyIGluIHRoZSAiRmlyc3QgRm91ciIgcm91bmQuIFdpdGhpbiB0aGlzIGZpZWxkIG9mIDY0LCB0aGV5J3JlIHNwbGl0IGJldHdlZW4gZm91ciAicmVnaW9ucyIgb2YgYSBicmFja2V0LCAqKlNvdXRoKiosICoqV2VzdCoqLCAqKkVhc3QqKiwgYW5kICoqTWlkd2VzdCoqLiBUaGUgdGVhbXMgaW4gZWFjaCByZWdpb24gYXJlIHJhbmtlZCBieSB0aGUgTkNBQSBDb21taXR0ZWUgYW5kIGdpdmVuIGEgInNlZWQiIGJldHdlZW4gIzEgYW5kICMxNi4gVGhvc2UgdGVhbXMgYXJlIHRoZW4gbWF0Y2hlZCB1cCBhZ2FpbnN0IGVhY2ggb3RoZXIgc28gdGhhdCAjMSBwbGF5cyAjMTYsICMyIHBsYXlzICMxNSwgIzMgcGxheXMgIzE0LCBhbmQgc28gb24uIFdlJ2xsIHJldmlzaXQgdGhlIHNlZWRpbmcgYW5kIHRlYW0gYnJlYWtkb3duIGxhdGVyLCBidXQgdGhpcyBzaG91bGQgZ2l2ZSB0aG9zZSB1bmZhbWlsaWFyIHdpdGggdGhlIHRvdXJuYW1lbnQgYSBnZW5lcmFsIGlkZWEgb2YgdGhlIGZvcm1hdC4gDQoNCkVhY2ggeWVhciwgb25jZSB0aGUgZmllbGQgb2YgNjQgaXMgZXN0YWJsaXNoZWQsIHRlbnMgb2YgbWlsbGlvbnMgYXJvdW5kIHRoZSB3b3JsZCB0cnkgdGhlaXIgYmVzdCB0byBwcmVkaWN0IHRoZSB3aW5uZXJzIGFuZCBsb3NlcnMgb2YgZWFjaCBnYW1lIGFjcm9zcyBhbGwgNjcgdGhhdCBhcmUgcGxheWVkIHRocm91Z2hvdXQgdGhlIHRvdXJuYW1lbnQsIHdoaWNoIG5hcnJvd3MgdGhlIGZpZWxkIGRvd24gdG8ganVzdCB0d28gdGVhbXMgd2hvIHdpbGwgcGxheSBmb3IgdGhlIE5hdGlvbmFsIENoYW1waW9uc2hpcCB0aXRsZS4gVG8gdGhpcyBkYXksIG5vYm9keSBoYXMgZXZlciBjb3JyZWN0bHkgcHJlZGljdGVkIGFsbCA2NyBvdXRjb21lcyBwZXJmZWN0bHkuIFtBY2NvcmRpbmcgdG8gdGhlIE5DQUFdKGh0dHBzOi8vd3d3Lm5jYWEuY29tL25ld3MvYmFza2V0YmFsbC1tZW4vYnJhY2tldGlxLzIwMjUtMDMtMjMvbG9uZ2VzdC1uY2FhLWJyYWNrZXQtaGFzLWV2ZXItc3RheWVkLXBlcmZlY3QpLCB0aGUgY2xvc2VzdCBhbnlvbmUgaGFzIGV2ZXIgY29tZSB0byBhIHBlcmZlY3QgYnJhY2tldCB3YXMgR3JlZ2cgTmlnbCwgYSBuZXVyb3BzeWNob2xvZ2lzdCBmcm9tIENvbHVtYnVzLCBPaGlvIHdobyBjb3JyZWN0bHkgcHJlZGljdGVkIHRoZSBvdXRjb21lcyBvZiA0OSBzdHJhaWdodCBnYW1lcyBiZWZvcmUgIzMgUHVyZHVlIGRlZmVhdGVkICMyIFRlbm5lc3NlZSBpbiBvdmVydGltZSBvZiB0aGUgc2Vjb25kIGdhbWUgaW4gdGhlIFN3ZWV0IDE2LiANCg0KVGhpcyB5ZWFyLCBJIGRlY2lkZWQgdG8gdGFrZSBhIG1vcmUgYW5hbHl0aWNhbCBhcHByb2FjaCB0byBidWlsZGluZyBteSBvd24gYnJhY2tldC4gQWZ0ZXIgdGhyZWUgZGF5cyBvZiByZXNlYXJjaGluZyBwcmVkaWN0aXZlIHZhbHVlcyBpbiBiYXNrZXRiYWxsLCByZWFkaW5nIHBhcGVycywgYW5kIGpvdXJuYWxpbmcgYWxsIG9mIG15IGZpbmRpbmdzLCBJIGZvdW5kIGEgW2Jsb2cgcG9zdF0oaHR0cHM6Ly93d3cuZGF0YS1hY3Rpb24tbGFiLmNvbS8yMDIxLzExLzIxL3ByZWRpY3RpdmUtYW5hbHl0aWNzLWluLWNvbGxlZ2UtYmFza2V0YmFsbC8pIGZyb20gMjAyMSBhYm91dCBhbiBSIFByb2plY3QgdXNpbmcgYSBiaW5vbWlhbCBkaXN0cmlidXRpb24gYXBwcm9hY2ggSSBoYWRuJ3Qgc2VlbiBhbnl3aGVyZSBlbHNlIGJlZm9yZS4gSSB0cmllZCBteSBiZXN0IHRvIGVtdWxhdGUgdGhhdCBwcm9jZWR1cmUgd2l0aCBteSBsaW1pdGVkIGFiaWxpdGllcyBhdCB0aGUgdGltZSwgYnV0IGluIHRoZSBlbmQgd2FzIHVuc2F0aXNmaWVkIHdpdGggdGhlIHVuY2VydGFpbiBxdWFsaXR5IG9mIG15IHdvcmsuIEkgZWxlY3RlZCBub3QgdG8gZW1iYXJyYXNzIG15c2VsZiBieSBzdWJqZWN0aW5nIHRoaXMgbW9kZWwgdG8gdGhlIHNjcnV0aW55IG9mIG15IHBlZXJzLCBhbmQga2VwdCB0aGUgcmVzdWx0cyBidXJpZWQgaW4gYW4gYWxtb3N0IGluZGVjaXBoZXJhYmxlIHNwcmVhZHNoZWV0LiBUaGlzIHVuY2VydGFpbnR5IHByb3ZlZCB0byBiZSBmb29saXNoLCBob3dldmVyLCBhcyBhbGwgb2YgdGhhdCB3b3JrIGRvbmUgZXhjbHVzaXZlbHkgaW4gTWljcm9zb2Z0IEV4Y2VsIGFuZCBzZXZlcmFsIHBhZ2VzIG9mIGhhbmR3cml0dGVuIG5vdGVzIHdhcyBhYmxlIHRvIGNvcnJlY3RseSBwcmVkaWN0ICoqNTYvNjcqKiBvdXRjb21lcyBhY3Jvc3MgdGhlIGVudGlyZSB0b3VybmFtZW50LiBUaGUgZ29hbCwgdW5mb3J0dW5hdGVseSwgaXMgYSBwZXJmZWN0ICoqNjcvNjcqKi4gVGhpcyBjaGFsbGVuZ2UgaGFzIHN0dW1wZWQgbWF0aGVtYXRpY2lhbnMsIGVjb25vbWlzdHMsIGFuYWx5c3RzLCBhbmQgZXZlcnlkYXkgYmFza2V0YmFsbCBmYW5zIGFsaWtlIGZvciBkZWNhZGVzLiBUaGUgcXVlc3Rpb24gdGhhdCBldmVyeW9uZSBhc2tzIGVhY2ggTWFyY2ggaXMgdGhlIHNhbWUsICJ3aGF0IHRlYW1zIGFyZSBnb2luZyB0byBwdWxsIG9mZiBhbiB1cHNldD8iIA0KDQpJZiBjaG9vc2luZyBhIHBlcmZlY3QgYnJhY2tldCB3ZXJlIGFzIHNpbXBsZSBhcyBwaWNraW5nIHRoZSAiZmF2b3JpdGUiIGluIGVhY2ggZ2FtZSBieSB0aGVpciBzZWVkaW5nLCB3ZSdkIGV4cGVjdCB0byBzZWUgYSBGaW5hbCBGb3VyIG9mIGZvdXIgIzEgc2VlZHMgZXZlcnkgeWVhciwgYnV0IHdlIGtub3cgdGhhdCdzIG5vdCB0aGUgY2FzZS4gSW4gZmFjdCwgaXQncyBvbmx5IGhhcHBlbmVkIHR3aWNlOiAqKjIwMDgqKidzIEZpbmFsIEZvdXIgZmVhdHVyZWQgIzEgc2VlZHMgS2Fuc2FzLCBNZW1waGlzLCBOb3J0aCBDYXJvbGluYSwgYW5kIFVDTEEuIFRoZSBvbmx5IG90aGVyIHllYXIgaXQncyBoYXBwZW5lZD8gKioyMDI1KiouIFRoaXMgeWVhcidzIEZpbmFsIEZvdXIgb2YgIzEgc2VlZHMgQXVidXJuLCBEdWtlLCBGbG9yaWRhLCBhbmQgSG91c3RvbiBhY2hpZXZlZCB0aGF0IGZlYXQgZm9yIGp1c3QgdGhlIHNlY29uZCB0aW1lIGV2ZXIuIERlc3BpdGUgdGhpcywgd2UgZW50ZXIgdGhlIDIwMjUtMjYgQ29sbGVnZSBCYXNrZXRiYWxsIHNlYXNvbiB3aXRoIG5vYm9keSBldmVyIGNvcnJlY3RseSBjcmFmdGluZyBhIHBlcmZlY3QgYnJhY2tldC4gDQoNClNvLCB3aGF0IHRlYW1zIHB1bGxlZCBvZmYgYW4gInVwc2V0Ij8gVG8gYW5zd2VyIHRoYXQgcXVlc3Rpb24gd2UgZmlyc3QgbmVlZCB0byBzcGxpdCBpdCBpbnRvIHR3byBwYXJ0cy4gV2hpY2ggdGVhbXMgd2VyZSAqYWN0dWFsbHkqIGZhdm9yZWQgaW4gZWFjaCBnYW1lLCBhbmQgd2hvIHdvbj8gVGhlIGxhdHRlciBpcyBlYXN5IHRvIGFuc3dlciwgYXMgZWFjaCBnYW1lIHdhcyBwbGF5ZWQgaW4gTWFyY2gvQXByaWwgb2YgMjAyNSwgYW5kIHdlIGhhdmUgYWxsIHRoZSByZXN1bHRzIHJlYWRpbHkgYXZhaWxhYmxlLiBUaGUgZm9ybWVyLCBub3Qgc28gbXVjaC4gSW4gb3JkZXIgdG8gc3RhcnQgYW5zd2VyaW5nIHRoYXQgcXVlc3Rpb24sIGxldCdzIHNldCB0aGUgc3RhZ2UuDQoNCjxicj4NCg0KIyBUaGUgQnJhY2tldA0KDQpFYWNoIHRlYW0gaW4gdGhlICpNYXJjaCBNYWRuZXNzKiB0b3VybmFtZW50IGlzIHZ5aW5nIGZvciBhIGNoYW5jZSB0byBwbGF5IGluIHRoZSBOYXRpb25hbCBDaGFtcGlvbnNoaXAuIFRob3NlIDY4IHRlYW1zIGFyZSBzZWxlY3RlZCBmcm9tIHRoZSBwb29sIG9mIGFsbCAzNjQgRGl2aXNpb24gSSB0ZWFtcyBpbiB0aGUgTkNBQS4gRWFjaCBvZiB0aGUgMzY0IHNjaG9vbHMgYXJlIHNwbGl0IGludG8gMzEgZGlmZmVyZW50IGNvbmZlcmVuY2VzLCB3aG8gcHJpbWFyaWx5IGNvbXBldGUgYWdhaW5zdCB0aGUgb3RoZXIgbWVtYmVycyBvZiB0aGVpciBjb25mZXJlbmNlIGluIHRoZSByZWd1bGFyIHNlYXNvbi4gQXQgdGhlIGNvbmNsdXNpb24gb2YgdGhlIHJlZ3VsYXIgc2Vhc29uIGVhY2ggY29uZmVyZW5jZSBob3N0cyB0aGVpciBvd24gc2luZ2xlLWVsaW1pbmF0aW9uIHRvdXJuYW1lbnQsIGFuZCB0aGUgd2lubmVyIG9mIHRoYXQgdG91cm5hbWVudCByZWNlaXZlcyBhbiAiYXV0b21hdGljIGJpZCIgdG8gcGxheSBpbiB0aGUgKk1hcmNoIE1hZG5lc3MqIHRvdXJuYW1lbnQuIFRoZSByZW1haW5pbmcgMzcgc3BvdHMgaW4gdGhlIHRvdXJuYW1lbnQgYXJlIGRlY2lkZWQgYnkgdGhlIE5DQUEgQ29tbWl0dGVlLCB3aG8gYXdhcmRzICJhdC1sYXJnZSIgYmlkcy4gVGhlc2UgZ28gdG8gd2hpY2hldmVyIHRlYW1zIHRoZXkgZGVlbSB0byBiZSB0aGUgMzcgYmVzdCBpbiB0aGUgY291bnRyeSwgYnV0IGRpZG4ndCB3aW4gdGhlaXIgY29uZmVyZW5jZSBhbmQgcmVjZWl2ZSBhbiBhdXRvbWF0aWMgYmlkLiANCg0KRm9yIGEgbnVtYmVyIG9mIHJlYXNvbnMsIHRoaXMgc2VsZWN0aW9uIHByb2Nlc3MgaXMgd2hlcmUgdGhlICJtYWRuZXNzIiBiZWdpbnMuIEFueSB0ZWFtIGluIHRoZSBjb3VudHJ5LCByZWdhcmRsZXNzIG9mIGhvdyBiYWQgdGhleSB3ZXJlIHRocm91Z2hvdXQgdGhlIHJlZ3VsYXIgc2Vhc29uLCBqdXN0IG5lZWRzIHRvIHF1YWxpZnkgZm9yIHRoZWlyIGNvbmZlcmVuY2UgdG91cm5hbWVudCB0byBoYXZlIGEgc2hvdCBhdCBkYW5jaW5nLiBJZiB0aGV5IGNhbiBnZXQgaG90IGluIHRoZWlyIGNvbmZlcmVuY2UgdG91cm5hbWVudCBhbmQgd2luIGl0LCB0aGV5IHJlY2VpdmUgYW4gYXV0b21hdGljIGJpZCBhbGwgdGhlIHNhbWUuIFdlJ2xsIHRha2UgYSBsb29rIGF0IHRoZSBkYXRhIGluIHRoZSBuZXh0IHNlY3Rpb24gYW5kIHdoZXJlIGl0IGNvbWVzIGZyb20sIGJ1dCBvbmUgb2YgdGhlICJ3b3JzdCIgdGVhbXMgaW4gdGhlIHRvdXJuYW1lbnQgdGhpcyB5ZWFyLCB0aGUgU2FpbnQgRnJhbmNpcyBSZWQgRmxhc2gsIGhhZCBhIHBlZGVzdHJpYW4gMTMtMTcgb3ZlcmFsbCByZWNvcmQgaGVhZGluZyBpbnRvIHRoZSBOb3J0aGVhc3QgQ29uZmVyZW5jZSAoTkVDKSBUb3VybmFtZW50LiBEZXNwaXRlIHRoaXMsIHRoZXkgd2VyZSBhYmxlIHRvIHNlY3VyZSB3aW5zIG92ZXIgV2FnbmVyLCBMSVUsIGFuZCBDZW50cmFsIENvbm5lY3RpY3V0IHRvIHdpbiB0aGUgTkVDIGFuZCBwdW5jaCB0aGVpciB0aWNrZXQgdG8gYmUgYSBwYXJ0IG9mIHRoZSBtYWRuZXNzLiANCg0KQXMgd2UgY2FuIHNlZSwgdGhlIGF1dG8tYmlkIHN5c3RlbSBpbnRyb2R1Y2VzIGEgbGV2ZWwgb2YgY2hhb3MgaW4gdGVybXMgb2YgKndobyogaXMgYWJsZSB0byBxdWFsaWZ5IGZvciB0aGUgdG91cm5hbWVudC4gTW91bnQgU3QuIE1hcnkncywgYW5vdGhlciBhdXRvLWJpZCB0ZWFtIG91dCBvZiB0aGUgTUFBQyAoTWV0cm8gQXRsYW50aWMgQXRobGV0aWMgQ29uZmVyZW5jZSkgd2FzIG1hdGNoZWQgdXAgd2l0aCBibHVlLWJsb29kIGJhc2tldGJhbGwgcHJvZ3JhbSBEdWtlIGluIHRoZSBSb3VuZCBvZiA2NC4gV2l0aCBhbiB1bmRlcmdyYWR1YXRlIHN0dWRlbnQgYm9keSBvZiAxLDgxNSwgTW91bnQgU3QuIE1hcnkncyBoYXMgYWJzb2x1dGVseSBubyBidXNpbmVzcyBwbGF5aW5nIER1a2UgaW4gYSBuYXRpb25hbGx5IHRlbGV2aXNlZCBiYXNrZXRiYWxsIGdhbWUsIGFuZCBzdWZmZXJlZCBhbiB1bmNvbXBldGl0aXZlIDkzLTQ5IGRlZmVhdC4gRGVzcGl0ZSB0aGUgY2xlYXIgZGlzY3JlcGFuY2llcyBpbiBzb21lIG1hdGNodXBzLCB0aGUgYXV0by1iaWQgc3lzdGVtIGFmZm9yZHMgdGhlIHNtYWxsZXIgY29uZmVyZW5jZXMvc2Nob29scyBhbiBlcXVhbCBvcHBvcnR1bml0eSB0byBtYWtlIGFuIGFwcGVhcmFuY2UgaW4gdGhlIHRvdXJuYW1lbnQuIA0KDQpXaGVuIGEgbmF0aW9uYWwgcG93ZXJob3VzZSBsaWtlIER1a2Ugc3F1YXJlcyBvZmYgYWdhaW5zdCBhIHNtYWxsLCBwcml2YXRlLCBsaWJlcmFsIGFydHMgc2Nob29sIGZyb20gcnVyYWwgTWFyeWxhbmQsIHdlIGNhbiByZWFzb25hYmx5IGFzc3VtZSB3aG8ncyBnb2luZyB0byB3aW4gdGhhdCBnYW1lLiBXaGlsZSB0aGF0J3Mgbm90IGFsd2F5cyB0aGUgY2FzZSAoc2VlIDIwMTggIzEgVmlyZ2luaWEgdnMuICMxNiBVTUJDLCBhbm90aGVyICMxNiBzZWVkIGZyb20gTWFyeWxhbmQgd2hvIGFjaGlldmVkIGEgbXVjaCBkaWZmZXJlbnQgcmVzdWx0KSwgd2UgZ2VuZXJhbGx5IGV4cGVjdCB0aGUgc21hbGxlciBjb25mZXJlbmNlcyB0byBzdHJ1Z2dsZSBhZ2FpbnN0IHRoZWlyIG11Y2ggbGFyZ2VyIGNvdW50ZXJwYXJ0cy4gVGhlIGF0LWxhcmdlIGJpZCBzeXN0ZW0sIG9uIHRoZSBvdGhlciBoYW5kLCBpbnRyb2R1Y2VzIGEgY29uc2lkZXJhYmxlIGFtb3VudCBvZiB1bmNlcnRhaW50eSB0byB0aGUgYnJhY2tldCBmb3IgYSBkaWZmZXJlbnQgcmVhc29uLiBUaGUgTkNBQSBDb21taXR0ZWUncyBleGFjdCBhcHByb2FjaCB0byBkZXRlcm1pbmluZyB0aGUgMzcgImJlc3QiIHJlbWFpbmluZyBzY2hvb2xzIGluIHRoZSBjb3VudHJ5LCBhZnRlciBhbGwgdGhlIGF1dG8tYmlkcyBoYXZlIGJlZW4gYXdhcmRlZCwgaGFzIGJlZW4gdGhlIHN1YmplY3Qgb2YgbXVjaCBkZWJhdGUgdGhyb3VnaG91dCB0aGUgdG91cm5hbWVudCdzIGVudGlyZSBleGlzdGVuY2UuIFdlIGNhbiByZWFzb25hYmx5IGFzc3VtZSB0aGF0IHRoZXkgdXNlIG11Y2ggb2YgdGhlIHNhbWUgY3JpdGVyaWEgdGhhdCB3ZSB3aWxsIHVzZSBpbiBvdXIgb3duIGRhdGEsIGJ1dCB0aGV5IGhhdmUgYW4gaWxsdXN0cmlvdXMgaGlzdG9yeSBvZiBiZWluZyAid3JvbmciIHdoZW4gbWFraW5nIHRob3NlIHNlbGVjdGlvbnMuIFNpbmNlIHRoZSBzZWxlY3Rpb24gcHJvY2VzcyBvZiBhdC1sYXJnZSBiaWRzIGlzbid0IHRoZSB0b3BpYyBvZiB0aGlzIHByb2plY3QsIHdlIHdvbid0IGdvIHRvbyBpbi1kZXB0aCBpbnRvIHdobyByZWNlaXZlcyB0aGVtLiBBbGwgd2UgbmVlZCB0byB1bmRlcnN0YW5kIGFib3V0IHRoZXNlIGF0LWxhcmdlIHRlYW1zIGlzIHRoYXQgdGhleSBhcmUgYmVsaWV2ZWQgdG8gaGF2ZSAqZWFybmVkKiB0aGVpciBiaWQgdGhyb3VnaCB0aGVpciBwbGF5IGFjcm9zcyB0aGUgZW50aXJlIHNlYXNvbiwgYW5kIHRoZWlyIHNlZWRpbmcgc2hvdWxkIHJlZmxlY3QgaG93IGdvb2Qgb2YgYSB0ZWFtIHRoZXkgYXJlLiBGb3IgaW5zdGFuY2UsIEF1YnVybiBsb3N0IGluIHRoZSBzZW1pZmluYWxzIG9mIHRoZSBTRUMgKFNvdXRoZWFzdGVybiBDb25mZXJlbmNlKSBUb3VybmFtZW50IHRvIFRlbm5lc3NlZS4gQWZ0ZXIgdGhleSBib3RoIHJlY2VpdmVkIGF0LWxhcmdlIGJpZHMsIEF1YnVybiB3YXMgZ2l2ZW4gYSAjMSBzZWVkLCBUZW5uZXNzZWUgYSAjMiBzZWVkLiANCg0KPGJyPg0KDQojIFRoZSBEYXRhDQoNCk5vdyB0aGF0IHdlIGhhdmUgYSBnZW5lcmFsIHVuZGVyc3RhbmRpbmcgb2Ygd2hhdCBzb3J0IG9mIHRlYW1zIG1ha2UgdGhlIHRvdXJuYW1lbnQsIGxldCdzIHRha2UgYSBsb29rIGF0IHRoZSBkYXRhIHdlJ2xsIGJlIHVzaW5nLiBUaGUgZmlyc3QsIG1vc3QgaW1wb3J0YW50IGRhdGFzZXQgd2UgaGF2ZSBhdCBvdXIgZGlzcG9zYWwgaXMgS2VuIFBvbWVyb3kncyAqKktlblBvbSoqIHJhbmtpbmdzLiBUaGVzZSBhcmUgdGhlIG51bWJlcnMgd2UnbGwgYmUgdXNpbmcgdG8gZG8gbW9zdCBvZiBvdXIgc2NvcmUgcHJlZGljdGlvbnMuIEFzIHBlciB0aGUgVGVybXMgb2YgVXNlIGZvciB0aGlzIGRhdGEsIGhlcmUgaXMgYSBsaW5rIHRvIHRoZSBbS2VuUG9tIFdlYnNpdGVdKGh0dHBzOi8va2VucG9tLmNvbS8pLg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgV2UgdXNlIHRoZSB0aWR5dmVyc2UgYW5kIERUIHBhY2thZ2VzIHRvIGRpc3BsYXkgb3VyIGRhdGEgaW4gYSBjbGVhbmVyIGZvcm1hdCBhcyB3ZSB3b3JrIHRocm91Z2ggaXQgDQojIGFsbC4gV2UgYWxzbyB1c2UgdGhlIHRpZHl2ZXJzZSBtdWNoIGxhdGVyIGluIHRoZSByZXBvcnQgdG8gY3JlYXRlIHNvbWUgdXNlZnVsIGdyYXBocyB0byBkcmF3IGluc2lnaHRzIA0KIyBhYm91dCBvdXIgZGF0YS4NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShEVCkNCiMgSSBpbml0aWFsbHkgdXNlZCBkcGx5ciBmb3Igc29tZSBkYXRhIHRyYW5zZm9ybWluZyBzdGVwcywgYnV0IG5vdyBpdCBleGlzdHMgb25seSB0byBpbnRlcmFjdCB3aXRoIG91ciANCiMgRFQgcGFja2FnZSwgDQpsaWJyYXJ5KGRwbHlyKQ0KIyBUaGlzIHdhcyBhIHBhY2thZ2UgSSBmb3VuZCBieSBhY2NpZGVudGFsbHkgY29uZnVzaW5nIFB5dGhvbiBhbmQgUiBzeW50YXgsIGJ1dCBpdCdzIGluY3JlZGlibHkgdXNlZnVsIA0KIyBmb3IgZGlzcGxheWluZyB0aGUgcmVzdWx0cyBvZiBvdXIgcHJlZGljdGlvbiBtb2RlbCB0aGF0IHdlJ2xsIGJlIHVzaW5nIHF1aXRlIGEgYml0IGxhdGVyLiANCmxpYnJhcnkoZ2x1ZSkNCiMgSW4gb3JkZXIgdG8gcG9pbnQgb3V0IGEgbnVtYmVyIG9mIHRlYW1zIGluIHRoZSBwbG90cyB3ZSdsbCBiZSBidWlsZGluZyB0byB0cnkgYW5kIHNldCBhcGFydCBzb21lIA0KIyBzcGVjaWZpYyB3aW5uZXJzIGFuZCBsb3NlcnMsIHdlIHVzZSBnZ2hpZ2hsaWdodCB0byBtYWtlIHRoZW0gc3RhbmQgb3V0IGFtb25nc3QgdGhlIGVudGlyZSBmaWVsZCBvZiA2NA0KbGlicmFyeShnZ2hpZ2hsaWdodCkNCmxpYnJhcnkoY2JicGxvdFIpDQoNCiMgUmVhZHMgaW4gb3VyIGZpcnN0IGRhdGFzZXQgYW5kIGZvcm1hdHMgaXQgbmljZWx5IGludG8gYSByZWFkYWJsZSBkYXRhdGFibGUNCmtwIDwtIHJlYWRfY3N2KCdrZW5wb20uY3N2JywgY29sX25hbWVzPVRSVUUpDQpkYXRhKGtwLCBwYWNrYWdlPSdnZ3Bsb3QyJykNCmRhdGF0YWJsZShrcCwgDQogICAgICAgICAgZXh0ZW5zaW9ucz0nU2Nyb2xsZXInLA0KICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFg9VFJVRSkpDQpgYGANCg0KPGJyPg0KDQoNClRoZXJlJ3MgYSBmZXcgdmFyaWFibGVzIGluIHRoaXMgZGF0YSB0aGF0IHdlIGRvbid0IG5lZWQsIHNvIHdlIGNhbiBzYWZlbHkgZ2V0IHJpZCBvZiB0aGVtLiBUaGUgb25seSBudW1iZXJzIHdlJ2xsIGJlIHVzaW5nIGZvciBub3cgYXJlIGBPUnRnYCwgYERSdGdgLCBhbmQgYEFkalRgLiBJdCBtYXkgbm90IHNlZW0gbGlrZSBtdWNoLCBidXQgdGhlc2UgdmFsdWVzIHJlcHJlc2VudCBhbG1vc3QgYWxsIHdlIG5lZWQgdG8gbWFrZSBzb21lIHN1cnByaXNpbmdseSBhY2N1cmF0ZSBhc3N1bXB0aW9ucyBhYm91dCBob3cgdGhlc2UgZ2FtZXMgd2lsbCBnby4gDQoNCiogYE9SdGdgIC0gQSBtZWFzdXJlIG9mIG9wcG9uZW50LWFkanVzdGVkIG9mZmVuc2l2ZSBlZmZpY2llbmN5LCBob3cgbWFueSBwb2ludHMgYSB0ZWFtIHNjb3JlcyBwZXIgMTAwIHBvc3Nlc3Npb25zLg0KDQoqIGBEUnRnYCAtIEEgbWVhc3VyZSBvZiBvcHBvbmVudC1hZGp1c3RlZCBkZWZlbnNpdmUgZWZmaWNpZW5jeSwgaG93IG1hbnkgcG9pbnRzIGEgdGVhbSBhbGxvd3MgcGVyIDEwMCBwb3NzZXNzaW9ucy4gDQoNCiogYEFkalRgIC0gQSBtZWFzdXJlIG9mIG9wcG9uZW50LWFkanVzdGVkICJ0ZW1wbywiIGhvdyBtYW55IHBvc3Nlc3Npb25zIGEgdGVhbSBoYXMgcGVyIDQwIG1pbnV0ZXMuIA0KDQo8YnI+DQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KIyBSZW5hbWVzIHNvbWUgb2YgdGhlIHZhcmlhYmxlcyB3ZSBuZWVkIHRoYXQgc2hhcmVkIGR1cGxpY2F0ZSBoZWFkZXJzIHdpdGggb3RoZXJzDQprcDEgPC0ga3AgfD4NCiAgcmVuYW1lKE9SdGcgPSBPUnRnLi4uNiwgRFJ0ZyA9IERSdGcuLi43KQ0KDQojIFJlbW92ZXMgdGhlIHZhcmlhYmxlcyB3ZSBkb24ndCBuZWVkIGZvciB0aGlzIHBhcnRpY3VsYXIgYW5hbHlzaXMNCmtwMiA8LSBrcDEgfD4NCiAgc2VsZWN0KC0oQ29uZjpOZXRSdGcuLi41KSwgLShMdWNrOk5ldFJ0Zy4uLjEzKSkNCg0KIyBPbmNlIGFnYWluIHVzZXMgdGhlIERUIHBhY2thZ2UgdG8gZGlzcGxheSBvdXIgZGF0YSBpbiBhIHJlYWRhYmxlIGRhdGF0YWJsZQ0KZGF0YShrcDIsIHBhY2thZ2U9J2dncGxvdDInKQ0KZGF0YXRhYmxlKGtwMiwgDQogICAgICAgICAgZXh0ZW5zaW9ucz0nU2Nyb2xsZXInLA0KICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFg9VFJVRSkpDQpgYGANCg0KPGJyPg0KDQpCZWZvcmUgd2UgbW92ZSBvbiwgd2UncmUgZ29pbmcgdG8gbmVlZCBhIGZldyBhdmVyYWdlcyBmcm9tIHRoaXMgZGF0YSB0byBiZSB1c2VkIGxhdGVyIGFzIHdlbGwgLiBFYWNoIG9mIHRoZW0gd2lsbCBiZSBkaXNjdXNzZWQgbGF0ZXIsIGJ1dCBmb3Igbm93IHRoZSBhdmVyYWdlcyB3ZSBuZWVkIGFyZToNCg0KKiBgQWRqVG5jYWFgDQoNCiogYGVGR09uY2FhYCANCg0KKiBgZUZHRG5jYWFgIA0KDQoqIGBEUnRnbmNhYWANCg0KKiBgcHBwbmNhYWANCg0KYGVGR09uY2FhYCBhbmQgYGVGR0RuY2FhYCBhcmUgdHdvIGZpZ3VyZXMgSSBjYWxjdWxhdGVkIHNlcGFyYXRlbHkgb3V0c2lkZSBvZiB0aGlzIHdvcmsgYW5kIGhhdmUgb24gaGFuZCwgc28gSSdsbCBiZSBhc3NpZ25pbmcgdGhvc2UgdmFsdWVzIG1hbnVhbGx5LiBUaGV5IGNvbWUgZnJvbSBUZWFtUmFua2luZ3MsIHdoaWNoIGlzIGludHJvZHVjZWQgYmVsb3cuDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBGaW5kaW5nIC8gYXNzaWduaW5nIGFsbCBvZiB0aGUgYXZlcmFnZSB2YWx1ZXMgd2UnbGwgbmVlZCBsYXRlcg0KDQpBZGpUbmNhYSA8LSBtZWFuKGtwMiRBZGpUKQ0KDQplRkdPbmNhYSA8LSAwLjUwNzYNCg0KZUZHRG5jYWEgPC0gMC41MDk2DQoNCkRSdGduY2FhIDwtIG1lYW4oa3AyJERSdGcpDQoNCnBwcE9uY2FhIDwtIG1lYW4oa3AyJE9SdGcgLyAxMDApDQpgYGANCg0KPGJyPg0KDQpOb3cgdGhhdCB3ZSBoYXZlIHRoZSBLZW5Qb20gZGF0YSwgd2UncmUgZ29pbmcgdG8gbmVlZCBzb21lIG1vcmUgdGVhbS1zcGVjaWZpYyBkYXRhLiBUaGVzZSBhcmUgYWxsIG51bWJlcnMgdGhhdCBJIGNvbGxlY3RlZCBtYW51YWxseSwgdGVhbSBieSB0ZWFtLCBpbiBNYXJjaCBmcm9tIHRoZSBvZmZpY2lhbCBbTkNBQSBTdGF0aXN0aWNzXShodHRwczovL3N0YXRzLm5jYWEub3JnL3NlbGVjdGlvbl9yYW5raW5ncy9uaXR0eV9ncml0dGllcy80MzMzNCkgd2Vic2l0ZSBhbmQgW1RlYW1SYW5raW5nc10oaHR0cHM6Ly93d3cudGVhbXJhbmtpbmdzLmNvbS8pLCBhbmQgdGhleSdyZSBhbHJlYWR5IHN1YnNldCB0byBqdXN0IHRoZSB0ZWFtcyB0aGF0IHBsYXllZCBpbiB0aGUgMjAyNSAqTWFyY2ggTWFkbmVzcyogdG91cm5hbWVudC4gU2luY2Ugd2Ugb25seSB3YW50IHRvIGxvb2sgYXQgdGhpcyBzdWJzZXQgZGF0YSwgd2UgY2FuIHVzZSBhbiBpbm5lciBqb2luIHRvIGdldCB0aGUgYWxtb3N0IGNvbXBsZXRlLCBjb3JyZWN0bHkgc3Vic2V0IGRhdGEgd2UgbmVlZCBjb250YWluaW5nIGp1c3QgdGhlIDY4IHRlYW1zIGluIHRoZSB0b3VybmFtZW50IHRoaXMgeWVhci4NCg0KPGJyPg0KDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgUmVhZHMgaW4gb3VyIHRlYW0gc3RhdGlzdGljcyBhbmQgam9pbnMgaXQgd2l0aCBvdXIga2VucG9tIGRhdGEgc28gd2UgaGF2ZSBldmVyeXRoaW5nIGluIG9uZSBwbGFjZQ0KdGVhbXN0YXRzIDwtIHJlYWRfY3N2KCd0ZWFtX3N0YXRzLmNzdicsICkNCnN0YXRzIDwtIGlubmVyX2pvaW4odGVhbXN0YXRzLCBrcDIsIGJ5ID0gJ3RlYW0nKQ0KDQojIExpa2UgYmVmb3JlLCBkaXNwbGF5cyBhbGwgb3VyIGRhdGEgaW4gYSBjbGVhbiwgcmVhZGFibGUsIGRhdGF0YWJsZQ0KZGF0YShzdGF0cywgcGFja2FnZT0nZ2dwbG90MicpDQpkYXRhdGFibGUoc3RhdHMsIA0KICAgICAgICAgIGV4dGVuc2lvbnM9J1Njcm9sbGVyJywNCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzY3JvbGxYPVRSVUUpKQ0KYGBgDQoNCjxicj4NCg0KTm93LCB0aGlzIGlzIGEgZmFpciBhbW91bnQgb2YgdGVhbSBzdGF0aXN0aWNzLiBSZWFsaXN0aWNhbGx5IHdlIGRvbid0IG5lZWQgYWxsIG9mIGl0IHRvIGZpZ3VyZSBvdXQgb3VyIGV4cGVjdGVkIHdpbm5lcnMgYW5kIGxvc2Vycy4gQnV0LCB3ZSdsbCBiZSB0YWtpbmcgYSBsb29rIGF0IHNvbWUgb2YgdGhlIHN0YXRzIHdlIGRpZG4ndCB1c2UgbGF0ZXIgdG8gZmlndXJlIG91dCBpZiBzb21ldGhpbmcgd2FzIG1pc3NpbmcgZnJvbSBvdXIgcHJlZGljdGlvbnMsIGFuZCBob3cgd2UgY2FuIGJldHRlciBwcmVkaWN0IHdpbm5lcnMgYW5kIGxvc2VycyBpbiB0aGUgZnV0dXJlLiANCg0KSW4gYWRkaXRpb24gdG8gd2hhdCB3ZSBoYXZlIGFscmVhZHksIHdlJ3JlIGdvaW5nIHRvIGNhbGN1bGF0ZSBhIGZldyBtb3JlIHN0YXRzIHRoYXQgd2UgY2FuIHVzZS4gVGhlIGZpcnN0IG9mIHRoZXNlIGlzIGBwcHBPYCBhbmQgYHBwcERgLCB3aGljaCBhcmUgUG9pbnRzIHBlciBQb3NzZXNzaW9uIG9uIGJvdGggb2ZmZW5zZSBhbmQgZGVmZW5zZSwgcmVzcGVjdGl2ZWx5LiBUaGlzIGlzIHdoZXJlIHRoZSBLZW5Qb20gZGF0YSBiZWdpbnMgdG8gZGVtb25zdHJhdGUgaG93IHVzZWZ1bCBpdCBpcy4gVGhlIGBPUnRnYCBhbmQgYERSdGdgIHN0YXRpc3RpY3MgYXJlIG9wcG9uZW50IGFkanVzdGVkIGVmZmljaWVuY2llcyBmb3IgYm90aCBwb2ludHMgc2NvcmVkIG9uIG9mZmVuc2UgYW5kIGFsbG93ZWQgb24gZGVmZW5zZSByZXNwZWN0aXZlbHksIHBlci0xMDAgcG9zc2Vzc2lvbnMuIFRoZXJlZm9yZSwgd2UgY2FuIGRpdmlkZSB0aG9zZSBudW1iZXJzIGJ5IDEwMCB0byBnZXQgb3VyIGBwcHBPYCBhbmQgYHBwcERgLiANCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgR2l2ZXMgdXMgYSBwZXItcG9zc2Vzc2lvbiBhbHRlcm5hdGl2ZSB0byBvZmZlbnNpdmUgYW5kIGRlZmVuc2l2ZSBlZmZpY2llbmN5LCByYXRoZXIgDQojIHRoYW4gcGVyLTEwMCBwb3NzZXNzaW9ucw0Kc3RhdHMxIDwtIHN0YXRzIHw+DQogIG11dGF0ZShwcHBPID0gT1J0ZyAvIDEwMCwNCiAgICAgICAgIHBwcEQgPSBEUnRnIC8gMTAwKQ0KYGBgDQoNCjxicj4NCg0KV2hpbGUgaW4gb3VyIGV4cGVjdGVkIHBvaW50cyBjYWxjdWxhdGlvbnMgd2Ugd29uJ3QgYmUgdXNpbmcgdGhlc2UgYHBwcE9gIGFuZCBgcHBwRGAgZmlndXJlcyB0aGVtc2VsdmVzLCBvcHRpbmcgdG8gdXNlIHRoZSBgT1J0Z2AgYW5kIGBEUnRnYCBpbnN0ZWFkLCB0aGV5IG1pZ2h0IHByb3ZlIHVzZWZ1bCB3aGVuIHdlIHRha2UgYSBsb29rIGF0IHRoZSAidXBzZXRzIiBhZnRlciBjcmVhdGluZyBvdXIgYnJhY2tldCBzaW11bGF0aW9uLiBXZSdyZSBhbHNvIGdvaW5nIHRvIGNyZWF0ZSB0aHJlZSBtb3JlIHZhbHVlcyB0aGF0IG1heSBwcm92ZSB1c2VmdWwgbGF0ZXIgYXMgd2VsbC4gVGhlc2UgYXJlOiANCg0KKiBgZXByYCAoRWZmZWN0aXZlIFBvc3Nlc3Npb24gUmF0aW8pIC0gVGhlIG51bWJlciBvZiBzaG90IG9wcG9ydHVuaXRpZXMgYSB0ZWFtIGhhcyBwZXIgcG9zc2Vzc2lvbi4NCg0KKiBgdHNgIChUcnVlIFNob290aW5nKSAtICBTaW5jZSBiYXNrZXRiYWxsIGlzIHNjb3JlZCBpbiBpbmNyZW1lbnRzIG9mIDEsIDIsIGFuZCAzLCBgdHNgIHRlbGxzIHVzIHRoZSBwb2ludHMgcGVyIHNob3Qgb3Bwb3J0dW5pdHkgdGhhdCBlYWNoIHRlYW0gaGFzLiBUaGUgY29uc3RhbnQgMC40NzUgZXhpc3RzIGluIHRoZSBjYWxjdWxhdGlvbiBmb3IgdGhpcyBudW1iZXIgYmVjYXVzZSBvbmx5IGFib3V0IDQ3LjUlIG9mIEZyZWUgVGhyb3dzIGFjdHVhbGx5IGVuZCBhIHBvc3Nlc3Npb24uIERpZmZlcmVudCBzb3VyY2VzIGhhdmUgbGFuZGVkIG9uIGRpZmZlcmVudCBjb25zdGFudHMgdG8gdXNlIGZvciB0aGlzIGZpZ3VyZSwgYnV0IEtlblBvbSB1c2VzIDAuNDc1LCBzbyBJJ3ZlIGVsZWN0ZWQgdG8gc3RpY2sgd2l0aCBpdCBhcyB3ZWxsLg0KDQoqIGBwcHBgIChQb2ludHMgUGVyIFBvc3Nlc3Npb24pIC0gRXZlbiB0aG91Z2ggd2UgYWxyZWFkeSBoYXZlIG91ciBvcHBvbmVudC1hZGp1c3RlZCBgcHBwT2AgZm9yIGVhY2ggdGVhbSwgdGhpcyBmaWd1cmUgZ2l2ZXMgdXMgYW4gb2JqZWN0aXZlIGVzdGltYXRlIG9mIGVhY2ggdGVhbSdzIG9wcG9uZW50LWluZGVwZW5kZW50IHNjb3JpbmcgcHJvd2Vzcy4gSW4gYmFza2V0YmFsbCwgdGVhbXMgaGF2ZSB0aGUgc2FtZSBhbW91bnQgb2YgcG9zc2Vzc2lvbnMgZWFjaCBnYW1lICgrLy0gMSksIHNvIHR5cGljYWxseSB0aGUgdGVhbSB3aXRoIHRoZSBoaWdoZXIgYHBwcGAgd2lucy4gVXNpbmcgYGVwciB4IHRzYCB0byBmaW5kIGBwcHBgIGdpdmVzIHVzIGEgZ29vZCBlc3RpbWF0ZSBvZiBlYWNoIHRlYW0ncyBzY29yaW5nIGFiaWxpdHkuIEl0IGVzc2VudGlhbGx5IHRlbGxzIHVzIGhvdyBvZnRlbiBhIHRlYW0gc2hvb3RzLCBhbmQgaG93IG1hbnkgcG9pbnRzIHdlIGV4cGVjdCBvdXQgb2YgZWFjaCBzaG90LiANCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQojIENyZWF0ZXMgb3VyIGVwciwgdHMsIGFuZCBwcHAgdmFyaWFibGVzIGZvciBsYXRlciB1c2UgaWYgbmVlZGVkDQpzdGF0czIgPC0gc3RhdHMxIHw+DQogIG11dGF0ZShlcHIgPSAoKHBvc3MucGVyLmdhbWUgKyByZWIub2ZmKSAtIHRvLmcpIC8gcG9zcy5wZXIuZ2FtZSwNCiAgICAgICAgIHRzID0gc2NvcmluZy5vZmYgLyAoZmdhICsgKDAuNDc1ICogZnRhLmcpKSwNCiAgICAgICAgIHBwcCA9IGVwciAqIHRzKQ0KYGBgDQoNCjxicj4NCg0KV2UnbGwgYmUgY3JlYXRpbmcgYSBmZXcgbW9yZSB2YXJpYWJsZXMgdG8gbG9vayBhdCBvbmNlIHdlIHN0YXJ0IHRvIGRpdmUgaW50byBnYW1lIG91dGNvbWVzLCBhcyB3ZWxsIGFzIG1hdGNodXAgc3BlY2lmaWMgZGlmZmVyZW5jZXMgYmV0d2VlbiB0ZWFtcy4gRm9yIG5vdyB0aGVzZSBudW1iZXJzIGdpdmUgdXMgYSBzb2xpZCBmcmFtZXdvcmsgb2Ygd2hhdCBlYWNoIG9mIHRoZSB0ZWFtcyBpbiB0aGUgdG91cm5hbWVudCBicmluZ3MgdG8gdGhlIHRhYmxlLiANCg0KIyBXaGF0IElzIEEgJ0NpbmRlcmVsbGEgU3Rvcnk/Jw0KDQpJbiB0aGUgbmV4dCBzZWN0aW9ucyB3ZSdsbCB0YWtlIGEgbG9vayBhdCB3aGF0IGFjdHVhbGx5IGhhcHBlbmVkIGluIHRoZSAyMDI1ICpNYXJjaCBNYWRuZXNzKiB0b3VybmFtZW50LCBhbG9uZyB3aXRoIHdoYXQgdGhlIG1vZGVsIEkgbWVudGlvbmVkIGVhcmxpZXIgcHJlZGljdGVkIHdvdWxkIGhhcHBlbi4gQmVmb3JlIHRoYXQsIGhvd2V2ZXIsIEkgd2FudCB0byB0YWtlIGEgc3RlcCBiYWNrIHRvIGVsYWJvcmF0ZSBvbiB0aGUgdGl0bGUgb2YgdGhpcyBwcm9qZWN0LiBBICJDaW5kZXJlbGxhIFN0b3J5IiB0ZWFtIGluICpNYXJjaCBNYWRuZXNzKiB0eXBpY2FsbHkgcmVmZXJzIHRvIGFuIHVuZGVyZG9nLCBoaWdobHktc2VlZGVkIHRlYW0gdGhhdCBtYWtlcyBpdCBtdWNoIGZ1cnRoZXIgaW4gdGhlIHRvdXJuYW1lbnQgdGhhbiBhbnlvbmUgZXhwZWN0cyB0aGVtIHRvLiBXZSd2ZSBhbHJlYWR5IGRpc2N1c3NlZCB3aGljaCB0ZWFtcyBtYWtlIHRoZSB0b3VybmFtZW50LCBidXQgdGhlIHNlZWRpbmcgcHJvY2VzcyBpcyByZWxhdGl2ZWx5IHVua25vd24gb3V0c2lkZSBvZiB0aGUgcm9vbSB3aGVyZSB0aGUgTkNBQSBDb21taXR0ZWUgbWFrZXMgdGhlaXIgZGVjaXNpb25zLiBUaGlzIGlzIHdoZXJlIG91ciBtb2RlbCBkZXZpYXRlcyBmcm9tIHRoZSB0eXBpY2FsIGJyYWNrZXQtbWFrZXIncyBwZXJjZXB0aW9uIG9mIGVhY2ggZ2FtZS4gVGhlcmUgYXJlIG92ZXIgMSwwMDAgY29sbGVnZSBiYXNrZXRiYWxsIGdhbWVzIHBsYXllZCBhY3Jvc3MgdGhlIG5hdGlvbiBwcmlvciB0byAqTWFyY2ggTWFkbmVzcyosIHdoaWNoIGlzIHNpbXBseSB0b28gbWFueSBmb3IgYW55IG9uZSBwZXJzb24gdG8gd2F0Y2ggYWxsIG9mIHRoZW0sIGluY2x1ZGluZyB0aG9zZSBvbiB0aGUgY29tbWl0dGVlLiBUaGlzIGlzIHdoZXJlIHRoZXkgdGVuZCB0byBnZXQgc2VlZGluZyAid3JvbmciLCBhcyBJIGFsbHVkZWQgdG8gZWFybGllci4gV2hpbGUgb25lIHNjaG9vbCBtYXkgdGVjaG5pY2FsbHkgYmUgYmV0dGVyIHRoYW4gYW5vdGhlciBvbiBwYXBlciwgdGhleSBtYXkgbm90IG5lY2Vzc2FyaWx5IGJlIGZhdm9yaXRlcyB0byB3aW4gYWdhaW5zdCBhICJsZXNzZXIiIG9wcG9uZW50Lg0KDQpEdWUgdG8gdGhpcyBzZWVkaW5nLCBldmVuIGJlZm9yZSBhIHNpbmdsZSBnYW1lIGhhcyBiZWVuIHBsYXllZCBpbiB0aGUgUm91bmQgb2YgNjQgdGhlIENvbW1pdHRlZSBpbnRyb2R1Y2VzIGEgYmlhcyBpbiBmYXZvciBvZiBvbmUgdGVhbS4gSWYgeW91IGhhZG4ndCB3YXRjaGVkIGEgY29sbGVnZSBiYXNrZXRiYWxsIGdhbWUgYWxsIHNlYXNvbiwgeW91IG1heSBleHBlY3QgYSAjNyBvciAjMiBzZWVkIHRvIGRlZmVhdCBhICMxMCBzZWVkIHdpdGggcmVsYXRpdmUgZWFzZSwgYnV0IHRoaXMgeWVhciB0aGF0IHdhc24ndCB0aGUgY2FzZS4gRm9yICMxMCBBcmthbnNhcywgdGhleSBkZWZpZWQgdGhlIG9kZHMgaW4gYmFjayB0byBiYWNrIGdhbWVzIGFzIGEgKnRydWUqIENpbmRlcmVsbGEsIG5vdCBmYXZvcmVkIGluIGVpdGhlciBnYW1lIGJ5IHNlZWRpbmcgb3Igb3VyIG1vZGVsLiBUaGlzIGlzIHRoZSB0eXBlIG9mIHRlYW0gd2UncmUgbG9va2luZyB0byBpZGVudGlmeSAqKmJlZm9yZSoqIHRoZXkgYnVzdCBvdXIgYnJhY2tldC4gU28sIHdpdGggdGhhdCBpbiBtaW5kLCBsZXQncyBsb29rIGF0IHRoZSBnYW1lcy4gV2UnbGwgYmVnaW4gaW4gdGhlIFJvdW5kIG9mIDY0Lg0KDQojIFRoZSBNb2RlbA0KDQpTaW5jZSBhbGwgb2YgdGhlIGdhbWVzIGhhdmUgYWxyZWFkeSBiZWVuIHBsYXllZCwgd2UgY2FuIGZpbmQgdGhlIHNjb3JlcyBvbiB0aGUgaW50ZXJuZXQgYW5kIG1ha2UgZGVjbGFyYXRpb25zIGFib3V0IHRoZSBvdXRjb21lIHdpdGggdGhlIHBvd2VyIG9mIGhpbmRzaWdodC4gQnV0IGlmIHdlIHdhbnQgdG8gcHJlZGljdCB0aGUgb3V0Y29tZSBhaGVhZCBvZiB0aW1lLCB3ZSdyZSBnb2luZyB0byBuZWVkIHRvIHVzZSB0aGUgZGF0YSB3ZSBmb3VuZCBlYXJsaWVyIHRvIGZpbmQgb3Bwb25lbnQtYWRqdXN0ZWQgZXhwZWN0ZWQgdmFsdWVzIGZvciBlYWNoIG1hdGNodXAuIFRoZXNlIGVxdWF0aW9ucyBhcmUgdGFrZW4gZGlyZWN0bHkgZnJvbSB0aGUgYmxvZyBwb3N0IG1lbnRpb25lZCBlYXJsaWVyLCB3aXRoIHNvbWUgdmFyaWFibGVzIGFkanVzdGVkIHRvIGNvaW5jaWRlIHdpdGggb3VyIGRhdGEuIFdlJ2xsIHN0YXJ0IHdpdGggdGVtcG86DQoNCiogVXNpbmcgdGhlIGBBZGpUYCB2YWx1ZXMgZnJvbSBvdXIgS2VuUG9tIGRhdGEsIGFzIHdlbGwgYXMgdGhlIE5DQUEgYXZlcmFnZSB0aGF0IHdlIGNhbGN1bGF0ZWQgZWFybGllciwgd2UgY2FuIGVzdGltYXRlIHRoZSAidGVtcG8iIG9mIHRoZSBnYW1lLiBUaGlzIGlzIGEgcHJlZGljdGlvbiBmb3IgaG93IG1hbnkgcG9zc2Vzc2lvbnMgZWFjaCB0ZWFtIHdpbGwgaGF2ZSBwZXIgNDAgbWludXRlcy4gVGVhbXMgdGhhdCBwbGF5IGEgbG93ZXItdGhhbi1hdmVyYWdlIHRlbXBvIHRlbmQgdG8gY29udHJvbCB0aGUgcGFjZSBvZiB0aGUgZ2FtZS4gVGhleSdyZSB1c3VhbGx5IGNoYXJhY3Rlcml6ZWQgYnkgaGF2aW5nIGxvdyBzaG90IHZvbHVtZSwgYnV0IGEgaGlnaCBtYWtlIHBlcmNlbnRhZ2UsIGZhdm9yaW5nIHF1YWxpdHkgc2hvdHMuIFRlYW1zIHdpdGggYSBoaWdoZXItdGhhbi1hdmVyYWdlIHRlbXBvIGFyZSB1c3VhbGx5IHRoZSBvcHBvc2l0ZSwgZmF2b3JpbmcgYSBoaWdoIHNob3Qgdm9sdW1lIGJ1dCBsb3dlciBtYWtlIHBlcmNlbnRhZ2VzLiBUaGVyZSdzIG5vdCBhICJjb3JyZWN0IiB3YXkgdG8gcGxheSBhIGdhbWUgb2YgYmFza2V0YmFsbCwgYnV0IHRoZXNlIGRpZmZlcmVudCB0ZWFtIGlkZW50aXRpZXMgaXMgc29tZXRoaW5nIHdlJ2xsIGludmVzdGlnYXRlIGxhdGVyLiBUaGUgZXhwZWN0ZWQgdGVtcG8gb2YgYSBnYW1lIHBsYXllZCBiZXR3ZWVuICpUZWFtIEEqIGFuZCAqVGVhbSBCKiBpczoNCg0KPGJyPg0KDQp+X18qRXhwZWN0ZWQgVGVtcG8gZm9yIFRlYW0gQSB2cy4gQipfX34NClxiZWdpbnthbGlnbip9DQpFKFRlbXBvX3tBLCBCfSkgPSBcZnJhY3tBZGpUX3tBfX17QWRqVF97TkNBQX19ICogXGZyYWN7QWRqVF97Qn19e0FkalRfe05DQUF9fSAqIEFkalRfe05DQUF9DQpcZW5ke2FsaWduKn0NCg0KPGJyPg0KDQoqIFdlIGNhbiB1c2UgdGhpcyBleHBlY3RlZCB0ZW1wbyB2YWx1ZSB0byBmaW5kIG91ciBuZXh0IGltcG9ydGFudCBmaWd1cmUsIEV4cGVjdGVkIEZpZWxkIEdvYWxzIEF0dGVtcHRlZC4gVGhpcyB3aWxsIGdpdmUgdXMgYSBtZWFzdXJlIG9mIGhvdyBtYW55IHNob3RzICpUZWFtIEEqIGlzIGV4cGVjdGVkIHRvIHRha2UsIG9wcG9uZW50LWFkanVzdGVkIGZvciAqVGVhbSBCKidzIGRlZmVuc2UuIFRoZSBlcXVhdGlvbiB3ZSdsbCB1c2UgaXM6DQoNCn5fXypFeHBlY3RlZCBGaWVsZCBHb2FscyBBdHRlbXB0ZWQgYnkgVGVhbSBBIHZzLiBUZWFtIEIqX19+DQpcYmVnaW57YWxpZ24qfQ0KRShGR0Ffe0F9KSA9IEZHQV97QX0gKiBcZnJhY3tFKFRlbXBvX3tBLCBCfSl9e0FkalRfe0F9fQ0KXGVuZHthbGlnbip9DQoNCiogTmV4dCwgd2UnbGwgY2FsY3VsYXRlIHRoZSBleHBlY3RlZCBgZUZHJWAgKEVmZmVjdGl2ZSBGaWVsZCBHb2FsIFBlcmNlbnRhZ2UpLiBXZSBoYXZlbid0IGV4cGxhaW5lZCBgZUZHJWAgeWV0LCBzbyB3aGF0IGlzIGl0PyBgZUZHJWAgaXMgc2ltaWxhciB0byBhIG1vcmUgY29tbW9uIG1lYXN1cmUsIGBGRyVgLiBgRkclYCBnaXZlcyB0aGUgcGVyY2VudGFnZSBvZiBmaWVsZCBnb2FscyBtYWRlIHBlciBmaWVsZCBnb2FscyBhdHRlbXB0ZWQuKiBgZUZHJWAgaXMgc2xpZ2h0bHkgbW9yZSBudWFuY2VkIHRoYW4gYEZHJWAgYmVjYXVzZSBpdCBhY2NvdW50cyBmb3IgYm90aCAyIGFuZCAzIHBvaW50IGJhc2tldHMuIFdoaWxlIEkgZGlkbid0IGV4cGxpY2l0bHkgY2FsY3VsYXRlIHRoZSBlRkclIHZhbHVlcyBpbiBvdXIgZGF0YXNldCBzaW5jZSB0aGV5J3JlIGF2YWlsYWJsZSBpbiB0aGUgVGVhbVJhbmtpbmdzIGRhdGEsIHRoZSBlcXVhdGlvbiBpcyBnaXZlbiBiZWxvdy4gIA0KDQoqPHN1Yj5UaGlzIGlzIGEgZ29vZCBvcHBvcnR1bml0eSB0byBtZW50aW9uIHRoYXQgaW4gYmFza2V0YmFsbCwgYSAiZmllbGQgZ29hbCIgaXMgc2ltcGx5IGEgc2hvdCBmcm9tIGFueXdoZXJlIG9uIHRoZSBjb3VydCBkdXJpbmcgbm9ybWFsIHBsYXksIGkuZS4gbm90IGEgZnJlZSB0aHJvdy4gVGhlc2UgYXJlIG5vdCB0aGUgc2FtZSBhcyB0aGUgZmllbGQgZ29hbHMgZm91bmQgaW4gZm9vdGJhbGwuPC9zdWI+DQoNCjxicj4NCg0Kfl9fKkVmZmVjdGl2ZSBGaWVsZCBHb2FsIFBlcmNlbnRhZ2UgKGVGRyUpKl9ffg0KXGJlZ2lue2FsaWduKn0NCmVGR1wlXCA9IFxmcmFje0ZHICsoMC41KjNQKX17RkdBfQ0KXGVuZHthbGlnbip9DQoNCn5fXypFeHBlY3RlZCBlRkclIGZvciBUZWFtIEEgdnMuIFRlYW0gQipfX34NClxiZWdpbnthbGlnbip9DQpFKGVGR08pX3tBfSA9IFxmcmFje2VGR09fe0F9fXtlRkdPX3tOQ0FBfX0gKiBcZnJhY3tlRkdEX3tCfX17ZUZHRF97TkNBQX19ICogZUZHT197QX0gKiBcZnJhY3sxfXsxMDB9DQpcZW5ke2FsaWduKn0NCg0KPGJyPg0KDQoqIE9uY2Ugd2UgaGF2ZSBib3RoIG9mIHRob3NlIHZhbHVlcywgd2UnbGwgZmluZCB0aGUgZXhwZWN0ZWQgcG9pbnRzIHNjb3JlZCBieSAqVGVhbSBBKiBhZ2FpbnN0ICpUZWFtIEIqLiBXZSBkbyB0aGlzIGJ5IG11bHRpcGx5aW5nICpUZWFtIEEqJ3MgYWRqdXN0ZWQgZWZmaWNpZW5jeSBvbiBvZmZlbnNlIGJ5ICpUZWFtIEIqJ3MgYWRqdXN0ZWQgZWZmaWNpZW5jeSBhcyB3ZWxsIGFzIHRoZSBleHBlY3RlZCB0ZW1wbyBvZiB0aGUgZ2FtZSB3ZSBjYWxjdWxhdGVkIGVhcmxpZXIsIG92ZXIgdGhlIGF2ZXJhZ2UgTkNBQSBkZWZlbnNpdmUgZWZmaWNpZW5jeS4gU2luY2Ugb3VyIGVmZmljaWVuY2llcyBgT1J0Z2AgYW5kIGBEUnRnYCBmcm9tIHRoZSBLZW5Qb20gcmFua2luZ3MgYXJlIGdpdmVuIGFzIHBvaW50cyBzY29yZWQvYWxsb3dlZCBwZXItMTAwIHBvc3Nlc3Npb25zIGJ5IG5hdHVyZSwgd2UgZW5kIHVwIHdpdGggdGhlIGV4cGVjdGVkIHBvaW50cyBmb3IgZWFjaCB0ZWFtLg0KDQo8YnI+DQoNCn5fXypFeHBlY3RlZCBQb2ludHMgZm9yIFRlYW0gQSB2cy4gVGVhbSBCKl9ffg0KXGJlZ2lue2FsaWduKn0NCkUoUG9pbnRzKV97QX0gPSBcZnJhY3tPUnRnX3tBfSAqIERSdGdfe0J9ICogRShUZW1wb197QSxCfSl9e0RSdGdfe05DQUF9fSAqIFxmcmFjezF9ezEwMH0NClxlbmR7YWxpZ24qfQ0KDQo8YnI+DQoNCkluIG15IGluaXRpYWwgZm9yYXkgaW50byB0aGlzIGJpbm9taWFsIGRpc3RyaWJ1dGlvbiBhcHByb2FjaCwgdGhpcyB3YXMgdGhlIHBvaW50IHdoZXJlIEkgc3RvcHBlZC4gVW5hd2FyZSBvZiBob3cgdG8gZWZmZWN0aXZlbHkgbW9kZWwgdGhlIGRpc3RyaWJ1dGlvbiB1c2luZyB0aGUgdmFyaWFuY2Ugd2UnbGwgbG9vayBhdCBuZXh0LCBJIGRlZW1lZCB0aGUgZXhwZWN0ZWQgc2NvcmUgc3VmZmljaWVudDsgYW5kIHRvIHNvbWUgZXh0ZW50IGl0IHdhcy4gSW4gNTYvNjcgZ2FtZXMgdGhlIHRlYW0gd2hvIHdhcyBleHBlY3RlZCB0byBzY29yZSBtb3JlIHBvaW50cyB1c2luZyB0aGlzIG1ldGhvZCwgZGlkLiBCdXQgdGhpcyB0aW1lIGFyb3VuZCB3ZSdsbCBsb29rIGF0IHRoZSB2YXJpYW5jZSBpbiBvcmRlciB0byBhZGQgd2luIHByb2JhYmlsaXRpZXMgdG8gb3VyIHByZWRpY3Rpb25zLiANCg0KPGJyPg0KDQoqIFRvIGNhbGN1bGF0ZSB0aGUgdmFyaWFuY2UgaW4gc2NvcmluZyBmb3IgKlRlYW0gQSogd2UnbGwgdXNlIHRoZSBmb3JtdWxhIGJlbG93LiBJZiB3ZSB2aWV3IGZpZWxkIGdvYWxzIGF0dGVtcHRlZCBhcyB0cmlhbHMsIGFuZCBvdXIgYGVGRyVgIGFzIHRoZSBwcm9iYWJpbGl0eSBvZiBzdWNjZXNzLCB3ZSBjYW4gZWFzaWx5IGZpbmQgdGhlIHZhcmlhbmNlIGZvciBvdXIgZGlzdHJpYnV0aW9uLiANCg0Kfl9fKkV4cGVjdGVkIFZhcmlhbmNlIGluIFNjb3JpbmcgZm9yIFRlYW0gQSB2cy4gVGVhbSBCKl9ffg0KXGJlZ2lue2FsaWduKn0NClZhcihQb2ludHNfe0F9KSA9IEUoRkdBX3tBfSkgKiBFKGVGR09fe0F9KSgxLWVGR09fe0F9KSAqIDINClxlbmR7YWxpZ24qfQ0KDQo8YnI+DQoNCk5vdyB0aGF0IHdlIGhhdmUgYWxsIHRoZSBlcXVhdGlvbnMgd2UnbGwgbmVlZCwgd2UgY2FuIGJlZ2luIHRvIHN0YXJ0IHB1dHRpbmcgdG9nZXRoZXIgb3VyIGJyYWNrZXQuIA0KDQo8YnI+DQoNCiMgQnVpbGRpbmcgdGhlIEJyYWNrZXQNCg0KVG8gcmVtYWluIHdpdGhpbiB0aGUgc2NvcGUgb2YgdGhpcyBwcm9qZWN0LCBJJ2xsIHJlZnJhaW4gZnJvbSBidWlsZGluZyBhbiBlbnRpcmUgYnJhY2tldCBzaW11bGF0aW9uLiBJbnN0ZWFkLCBvcHRpbmcgdG8gZ28gZ2FtZSBieSBnYW1lIGFuZCBtYW51YWxseSBlbnRlciB0aGUgbWF0Y2h1cHMgZm9yIGVhY2guIEJ1dCBpbiBvcmRlciB0byBkbyB0aGF0IGluIGEgcmVhc29uYWJsZSBhbW91bnQgb2YgdGltZSwgd2UncmUgZ29pbmcgdG8gbmVlZCB0byBwdXQgdG9nZXRoZXIgc29tZSBmdW5jdGlvbnMgdXNpbmcgdGhlIGVxdWF0aW9ucyB3ZSBqdXN0IGRlc2NyaWJlZCBhbmQgdGhlIGF2ZXJhZ2VzIHdlIGNhbGN1bGF0ZWQgZWFybGllci4NCg0KYGBge3J9DQojIEV4cGVjdGVkIFRlbXBvIGZvciBUZWFtIEEgdnMuIEINCmV0ZW1wbyA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICAoc3RhdHMyW3N0YXRzMiR0ZWFtID09IHRlYW1hLCAiQWRqVCJdIC8gQWRqVG5jYWEpICogKHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYiwgIkFkalQiXSAvIEFkalRuY2FhKSAqIEFkalRuY2FhDQp9DQoNCiMgRXhwZWN0ZWQgRmllbGQgR29hbHMgQXR0ZW1wdGVkIGJ5IFRlYW0gQSB2cy4gVGVhbSBCDQplZmdhYSA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICBzdGF0czJbc3RhdHMyJHRlYW0gPT0gdGVhbWEsICJmZ2EiXSAqIChldGVtcG8odGVhbWEsIHRlYW1iKSAvIHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYSwgIkFkalQiXSkNCn0NCg0KIyBFeHBlY3RlZCBGaWVsZCBHb2FscyBBdHRlbXB0ZWQgYnkgVGVhbSBCIHZzLiBUZWFtIEENCmVmZ2FiIDwtIGZ1bmN0aW9uKHRlYW1hLCB0ZWFtYil7DQogIHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYiwgImZnYSJdICogKGV0ZW1wbyh0ZWFtYSwgdGVhbWIpIC8gc3RhdHMyW3N0YXRzMiR0ZWFtID09IHRlYW1iLCAiQWRqVCJdKQ0KfQ0KDQojIEV4cGVjdGVkIGVGRyUgZm9yIFRlYW0gQSB2cy4gVGVhbSBCDQplZWZnb2EgPC0gZnVuY3Rpb24odGVhbWEsIHRlYW1iKXsNCiAgKHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYSwgImVGRyJdIC8gZUZHT25jYWEpICogKHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYiwgIm9wcC5lRkciXSAvIGVGR0RuY2FhKSAqIHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYSwgImVGRyJdDQp9DQoNCiMgRXhwZWN0ZWQgZUZHJSBmb3IgVGVhbSBCIHZzLiBUZWFtIEENCmVlZmdvYiA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICAoc3RhdHMyW3N0YXRzMiR0ZWFtID09IHRlYW1iLCAiZUZHIl0gLyBlRkdPbmNhYSkgKiAoc3RhdHMyW3N0YXRzMiR0ZWFtID09IHRlYW1hLCAib3BwLmVGRyJdIC8gZUZHRG5jYWEpICogc3RhdHMyW3N0YXRzMiR0ZWFtID09IHRlYW1iLCAiZUZHIl0NCn0NCg0KIyBFeHBlY3RlZCBQb2ludHMgZm9yIFRlYW0gQSB2cy4gVGVhbSBCDQplcG9pbnRzYSA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICAoKHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYSwgIk9SdGciXSAqIHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYiwgIkRSdGciXSAqIGV0ZW1wbyh0ZWFtYSwgdGVhbWIpKSAvIERSdGduY2FhKSAqICgxLzEwMCkNCn0NCg0KIyBFeHBlY3RlZCBQb2ludHMgZm9yIFRlYW0gQiB2cy4gVGVhbSBBDQplcG9pbnRzYiA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICAoKHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYiwgIk9SdGciXSAqIHN0YXRzMltzdGF0czIkdGVhbSA9PSB0ZWFtYSwgIkRSdGciXSAqIGV0ZW1wbyh0ZWFtYSwgdGVhbWIpKSAvIERSdGduY2FhKSAqICgxLzEwMCkNCn0NCg0KIyBFeHBlY3RlZCBWYXJpYW5jZSBpbiBTY29yaW5nIGZvciBUZWFtIEEgdnMuIFRlYW0gQiwgY29udmVydGVkIHRvIGEgbnVtZXJpYyB2YWx1ZSB0byBhdm9pZCBpc3N1ZXMgd2l0aCB0aGUgDQojICdtYXRjaHVwJyBmdW5jdGlvbiBpbnRyb2R1Y2VkIG5leHQNCnZhcnBvaW50c2EgPC0gZnVuY3Rpb24odGVhbWEsIHRlYW1iKXsNCiAgdmFyYSA8LSBlZmdhYSh0ZWFtYSwgdGVhbWIpICogKGVlZmdvYSh0ZWFtYSwgdGVhbWIpKigxIC0gZWVmZ29hKHRlYW1hLCB0ZWFtYikpKSAqIDINCiAgdmEgPC0gYXMubnVtZXJpYyh2YXJhKQ0KICByZXR1cm4odmEpDQp9DQoNCiMgRXhwZWN0ZWQgVmFyaWFuY2UgaW4gU2NvcmluZyBmb3IgVGVhbSBCIHZzLiBUZWFtIEENCnZhcnBvaW50c2IgPC0gZnVuY3Rpb24odGVhbWEsIHRlYW1iKXsNCiAgdmFyYiA8LSBlZmdhYih0ZWFtYSwgdGVhbWIpICogKGVlZmdvYih0ZWFtYSwgdGVhbWIpKigxIC0gZWVmZ29iKHRlYW1hLCB0ZWFtYikpKSAqIDINCiAgdmIgPC0gYXMubnVtZXJpYyh2YXJiKQ0KICByZXR1cm4odmIpDQp9DQoNCg0KIyBUaGlzIGZ1bmN0aW9uIHRha2VzIHRoZSBzY29yZXMgdGhhdCB3ZSBqdXN0IGZvdW5kIGZvciBUZWFtIEEgYW5kIFRlYW0gQiwgYW5kIGNvbmNhdGVuYXRlcyB0aGVtIHVzaW5nIHRoZSAiZ2x1ZSIgcGFja2FnZS4NCiMgV2UgY2FuIHVzZSB0aGlzIGZ1bmN0aW9uIHRvIG5vdyBydW4gdGhyb3VnaCB0aGUgZW50aXJlIHRvdXJuYW1lbnQgcm91bmQgYnkgcm91bmQuIA0KbWF0Y2h1cCA8LSBmdW5jdGlvbih0ZWFtYSwgdGVhbWIpew0KICBwYSA8LSByb3VuZChlcG9pbnRzYSh0ZWFtYSwgdGVhbWIpLCBkaWdpdHMgPSAyKQ0KICBwYiA8LSByb3VuZChlcG9pbnRzYih0ZWFtYSwgdGVhbWIpLCBkaWdpdHMgPSAyKQ0KICANCiAgdmEgPC0gdmFycG9pbnRzYSh0ZWFtYSwgdGVhbWIpDQogIHZiIDwtIHZhcnBvaW50c2IodGVhbWEsIHRlYW1iKQ0KICANCiAgIyBTaW5jZSB3ZSBrbm93IHRoZSBleHBlY3RlZCBzY29yZSBhbmQgdGhlIHZhcmlhbmNlLCB3ZSBjYW4gdXNlIHRob3NlIHRvIGZpbmQgd2luIHByb2JhYmlsaXRpZXMgZm9yIGVhY2ggdGVhbQ0KICB6IDwtIChwYSAtIHBiKSAvIHNxcnQodmEgKyB2YikNCiAgeiA8LSBhcy5udW1lcmljKHopDQogIA0KICAjIFVzaW5nIG91ciB6IHNjb3JlLCBmaW5kIHdpbiBwZXJjZW50YWdlIGEgYW5kIGINCiAgd3BhIDwtIHJvdW5kKHBub3JtKHopLCBkaWdpdHMgPSAzKQ0KICB3cGIgPC0gcm91bmQoMSAtIHBub3JtKHopLCBkaWdpdHMgPSAzKQ0KICANCiAgIyBEZWNsYXJlcyB0aGUgd2lubmVyIGJhc2VkIG9uIHRoZSBoaWdoZXIgd2luIHByb2JhYmlsaXR5DQogIGlmICh3cGEgPiB3cGIpew0KICAgIHdpbiA8LSB0ZWFtYQ0KICB9IGVsc2V7DQogICAgd2luIDwtIHRlYW1iDQogIH0NCiAgDQogICMgQ2FsY3VsYXRlcyB0aGUgZXhwZWN0ZWQgcG9pbnQgZGlmZmVyZW50aWFsDQogIGlmIChwYSA+IHBiKXsNCiAgICBwZCA8LSByb3VuZChwYSAtIHBiLCBkaWdpdHMgPSAyKQ0KICB9IGVsc2V7DQogICAgcGQgPC0gcm91bmQocGItcGEsIGRpZ2l0cyA9IDIpDQogIH0NCiAgDQogICMgVXNlcyB0aGUgImdsdWUiIHBhY2thZ2UgdG8gcHV0IGFsbCBvZiBvdXIgcmVzdWx0cyB0b2dldGhlciBpbnRvIGEgbmljZSBvdXRwdXQgYW5kIHByaW50cyBpdCBhZnRlcndhcmRzLg0KICBvdXQgPC0gZ2x1ZSgie3RlYW1hfSBFeHBlY3RlZCBzY29yZToge3BhfSwgDQogICAgICAgICAgICAgIHt0ZWFtYn0gRXhwZWN0ZWQgc2NvcmU6IHtwYn0sDQogICAgICAgICAgICAgIFByb2plY3RlZCBQb2ludCBEaWZmZXJlbnRpYWw6IHtwZH0NCiAgICAgICAgICAgICAgV2luIFByb2JhYmlsaXR5IGZvciB7dGVhbWF9OiB7d3BhfQ0KICAgICAgICAgICAgICBXaW4gUHJvYmFiaWxpdHkgZm9yIHt0ZWFtYn06IHt3cGJ9DQogICAgICAgICAgICAgIFByb2plY3RlZCB3aW5uZXI6IHt3aW59IikNCiAgDQogIG91dA0KfQ0KYGBgDQoNCjxicj4gDQoNCk5vdyB0aGF0IHdlIGhhdmUgb3VyIGZ1bmN0aW9ucywgd2UgY2FuIGVhc2lseSBydW4gdGhyb3VnaCBlYWNoIG1hdGNodXAgYW5kIHJlZHVjZSA2NyBiYXNrZXRiYWxsIGdhbWVzIHRvIGEgZmV3IGZ1bmN0aW9uIGNhbGxzLiANCg0KIyMgT3VyIFByZWRpY3Rpb25zey0udGFic2V0fQ0KIyMjIFJvdW5kIG9mIDY0IHstLnRhYnNldH0NCiMjIyMgVGhlIFNvdXRoIFJlZ2lvbiB7LX0NCg0KYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQptYXRjaHVwKCJBdWJ1cm4iLCAiQWxhYmFtYSBTdC4iKQ0KDQptYXRjaHVwKCJMb3Vpc3ZpbGxlIiwgIkNyZWlnaHRvbiIpDQoNCm1hdGNodXAoIk1pY2hpZ2FuIiwgIlVDIFNhbiBEaWVnbyIpDQoNCm1hdGNodXAoIlRleGFzIEEmTSIsICJZYWxlIikNCg0KbWF0Y2h1cCgiT2xlIE1pc3MiLCAiTm9ydGggQ2Fyb2xpbmEiKQ0KDQptYXRjaHVwKCJJb3dhIFN0LiIsICJMaXBzY29tYiIpDQoNCm1hdGNodXAoIk1hcnF1ZXR0ZSIsICJOZXcgTWV4aWNvIikNCg0KbWF0Y2h1cCgiTWljaGlnYW4gU3QuIiwgIkJyeWFudCIpDQpgYGANCg0KIyMjIyBUaGUgV2VzdCBSZWdpb24gey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiRmxvcmlkYSIsICJOb3Jmb2xrIFN0LiIpDQoNCm1hdGNodXAoIlVDb25uIiwgIk9rbGFob21hIikNCg0KbWF0Y2h1cCgiTWVtcGhpcyIsICJDb2xvcmFkbyBTdC4iKQ0KDQptYXRjaHVwKCJNYXJ5bGFuZCIsICJHcmFuZCBDYW55b24iKQ0KDQptYXRjaHVwKCJNaXNzb3VyaSIsICJEcmFrZSIpDQoNCm1hdGNodXAoIlRleGFzIFRlY2giLCAiVU5DVyIpDQoNCm1hdGNodXAoIkthbnNhcyIsICJBcmthbnNhcyIpDQoNCm1hdGNodXAoIlN0LiBKb2huJ3MgKE5ZKSIsICJPbWFoYSIpDQpgYGANCg0KIyMjIyBUaGUgRWFzdCBSZWdpb257LX0NCg0KYGBge3J9DQptYXRjaHVwKCJEdWtlIiwgIk1vdW50IFN0LiBNYXJ5J3MiKQ0KDQptYXRjaHVwKCJNaXNzaXNzaXBwaSBTdC4iLCAiQmF5bG9yIikNCg0KbWF0Y2h1cCgiT3JlZ29uIiwgIkxpYmVydHkiKQ0KDQptYXRjaHVwKCJBcml6b25hIiwgIkFrcm9uIikNCg0KbWF0Y2h1cCgiQllVIiwgIlZDVSIpDQoNCm1hdGNodXAoIldpc2NvbnNpbiIsICJNb250YW5hIikNCg0KbWF0Y2h1cCgiU2FpbnQgTWFyeSdzIChDQSkiLCAiVmFuZGVyYmlsdCIpDQoNCm1hdGNodXAoIkFsYWJhbWEiLCAiUm9iZXJ0IE1vcnJpcyIpDQpgYGANCg0KIyMjIyBUaGUgTWlkd2VzdCBSZWdpb24gey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiSG91c3RvbiIsICJTSVUgRWR3YXJkc3ZpbGxlIikNCg0KbWF0Y2h1cCgiR29uemFnYSIsICJHZW9yZ2lhIikNCg0KbWF0Y2h1cCgiQ2xlbXNvbiIsICJNY05lZXNlIikNCg0KbWF0Y2h1cCgiUHVyZHVlIiwgIkhpZ2ggUG9pbnQiKQ0KDQptYXRjaHVwKCJJbGxpbm9pcyIsICJYYXZpZXIiKQ0KDQptYXRjaHVwKCJLZW50dWNreSIsICJUcm95IikNCg0KbWF0Y2h1cCgiVUNMQSIsICJVdGFoIFN0LiIpDQoNCm1hdGNodXAoIlRlbm5lc3NlZSIsICJXb2Zmb3JkIikNCmBgYA0KDQojIyMjIFJlc3VsdHMgey19DQpTbywgaG93IGRpZCB3ZSBkbz8gTm90IGdvb2QgZW5vdWdoLCBpZiA2Ny82NyBpcyBvdXIgZXZlbnR1YWwgZ29hbC4gQnV0IGxldCdzIHRha2UgYSBsb29rIGF0IHdoYXQgZ2FtZXMgd2UgZ290IHdyb25nIGFuZCBrZWVwIGEgcnVubmluZyB0YWxseSAgaW4gdGhlICpSZXN1bHRzKiB0YWIgc28gdGhhdCB3ZSBjYW4gdGFrZSBhIGxvb2sgYXQgdGhvc2UgdGVhbXMgYWZ0ZXJ3YXJkcy4NCg0KVGhlIGdhbWVzIHdlIGdvdCB3cm9uZyBhbmQgdGhlaXIgcmVzcGVjdGl2ZSBXaW4gUHJvYmFiaWxpdGllczoNCg0KKiAqKiM4KiogTG91aXN2aWxsZSAoNjQuNyUpIHZzICoqIzkqKiBDcmVpZ2h0b24gKDM1LjMlKQ0KDQoqICoqIzcqKiBNYXJxdWV0dGUgKDYzLjglKSB2cyAqKiMxMCoqIE5ldyBNZXhpY28gKDM2LjIlKQ0KDQoqICoqIzYqKiBNaXNzb3VyaSAoNzguOCUpIHZzICoqIzExKiogRHJha2UgKDIxLjIlKQ0KDQoqICoqIzcqKiBLYW5zYXMgKDY4LjQlKSB2cyAqKiMxMCoqIEFya2Fuc2FzICgzMS42JSkNCg0KKiAqKiM1KiogQ2xlbXNvbiAoODAuOCUpIHZzICoqIzEyKiogTWNOZWVzZSAoMTkuMiUpDQoNCiMjIyBSb3VuZCBvZiAzMiB7LS50YWJzZXR9DQojIyMjIFRoZSBTb3V0aCBSZWdpb24gey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiQXVidXJuIiwgIkNyZWlnaHRvbiIpDQoNCm1hdGNodXAoIk1pY2hpZ2FuIiwgIlRleGFzIEEmTSIpDQoNCm1hdGNodXAoIk9sZSBNaXNzIiwgIklvd2EgU3QuIikNCg0KbWF0Y2h1cCgiTmV3IE1leGljbyIsICJNaWNoaWdhbiBTdC4iKQ0KYGBgDQoNCiMjIyMgVGhlIFdlc3QgUmVnaW9uIHstfQ0KDQpgYGB7cn0NCm1hdGNodXAoIkZsb3JpZGEiLCAiVUNvbm4iKQ0KDQptYXRjaHVwKCJDb2xvcmFkbyBTdC4iLCAiTWFyeWxhbmQiKQ0KDQptYXRjaHVwKCJEcmFrZSIsICJUZXhhcyBUZWNoIikNCg0KbWF0Y2h1cCgiQXJrYW5zYXMiLCAiU3QuIEpvaG4ncyAoTlkpIikNCmBgYA0KDQojIyMjIFRoZSBFYXN0IFJlZ2lvbiB7LX0NCg0KYGBge3J9DQptYXRjaHVwKCJEdWtlIiwgIkJheWxvciIpDQoNCm1hdGNodXAoIk9yZWdvbiIsICJBcml6b25hIikNCg0KbWF0Y2h1cCgiQllVIiwgIldpc2NvbnNpbiIpDQoNCm1hdGNodXAoIlNhaW50IE1hcnkncyAoQ0EpIiwgIkFsYWJhbWEiKQ0KYGBgDQoNCiMjIyMgVGhlIE1pZHdlc3QgUmVnaW9uIHstfQ0KDQpgYGB7cn0NCm1hdGNodXAoIkhvdXN0b24iLCAiR29uemFnYSIpDQoNCm1hdGNodXAoIk1jTmVlc2UiLCAiUHVyZHVlIikNCg0KbWF0Y2h1cCgiSWxsaW5vaXMiLCAiS2VudHVja3kiKQ0KDQptYXRjaHVwKCJVQ0xBIiwgIlRlbm5lc3NlZSIpDQpgYGANCg0KIyMjIyBSZXN1bHRzIHstfQ0KDQpUaGUgZ2FtZXMgd2UgZ290IHdyb25nIGFuZCB0aGVpciByZXNwZWN0aXZlIFdpbiBQcm9iYWJpbGl0aWVzOg0KDQoqICoqIzUqKiBNaWNoaWdhbiAoNDMuMiUpIHZzICoqIzQqKiBUZXhhcyBBJk0gKDU2LjglKQ0KDQoqICoqIzYqKiBPbGUgTWlzcyAoMzIuNyUpIHZzICoqIzMqKiBJb3dhIFN0LiAoNjcuMyUpDQoNCiogKiojMTAqKiBBcmthbnNhcyAoMjEuMiUpIHZzICoqIzIqKiBTdC4gSm9obidzICg3OC44JSkNCg0KKiAqKiM2KiogQllVICgzNC45JSkgdnMgKiojMyoqIFdpc2NvbnNpbiAoNjUuMSUpDQoNCiMjIyBTd2VldCBTaXh0ZWVuIHstLnRhYnNldH0NCiMjIyMgVGhlIFNvdXRoIFJlZ2lvbiB7LX0NCg0KYGBge3J9DQptYXRjaHVwKCJBdWJ1cm4iLCAiTWljaGlnYW4iKQ0KDQptYXRjaHVwKCJPbGUgTWlzcyIsICJNaWNoaWdhbiBTdC4iKQ0KYGBgDQoNCiMjIyMgVGhlIFdlc3QgUmVnaW9uIHstfQ0KDQpgYGB7cn0NCm1hdGNodXAoIkZsb3JpZGEiLCAiTWFyeWxhbmQiKQ0KDQptYXRjaHVwKCJUZXhhcyBUZWNoIiwgIkFya2Fuc2FzIikNCmBgYA0KDQojIyMjIFRoZSBFYXN0IFJlZ2lvbiB7LX0NCg0KYGBge3J9DQptYXRjaHVwKCJEdWtlIiwgIkFyaXpvbmEiKQ0KDQptYXRjaHVwKCJCWVUiLCAiQWxhYmFtYSIpDQpgYGANCg0KIyMjIyBUaGUgTWlkd2VzdCBSZWdpb24gey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiSG91c3RvbiIsICJQdXJkdWUiKQ0KDQptYXRjaHVwKCJLZW50dWNreSIsICJUZW5uZXNzZWUiKQ0KYGBgDQoNCiMjIyMgUmVzdWx0cyB7LX0NCg0KVGhlIGdhbWVzIHdlIGdvdCB3cm9uZyBhbmQgdGhlaXIgcmVzcGVjdGl2ZSBXaW4gUHJvYmFiaWxpdGllczoNCg0KKiAqKk5vbmUqKg0KDQojIyMgRWxpdGUgRWlnaHQgey0udGFic2V0fQ0KIyMjIyBUaGUgU291dGggUmVnaW9uIHstfQ0KDQpgYGB7cn0NCm1hdGNodXAoIkF1YnVybiIsICJNaWNoaWdhbiBTdC4iKQ0KYGBgDQoNCiMjIyMgVGhlIFdlc3QgUmVnaW9uIHstfQ0KDQpgYGB7cn0NCm1hdGNodXAoIkZsb3JpZGEiLCAiVGV4YXMgVGVjaCIpDQpgYGANCg0KIyMjIyBUaGUgRWFzdCBSZWdpb24gey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiRHVrZSIsICJBbGFiYW1hIikNCmBgYA0KDQojIyMjIFRoZSBNaWR3ZXN0IFJlZ2lvbiB7LX0NCg0KYGBge3J9DQptYXRjaHVwKCJIb3VzdG9uIiwgIlRlbm5lc3NlZSIpDQpgYGANCg0KIyMjIyBSZXN1bHRzIHstfQ0KDQpUaGUgZ2FtZXMgd2UgZ290IHdyb25nIGFuZCB0aGVpciByZXNwZWN0aXZlIFdpbiBQcm9iYWJpbGl0aWVzOg0KDQoqICoqTm9uZSoqDQoNCiMjIyBGaW5hbCBGb3VyIHstLnRhYnNldH0NCiMjIyMgU291dGgvV2VzdCB7LX0NCg0KYGBge3J9DQptYXRjaHVwKCJBdWJ1cm4iLCAiRmxvcmlkYSIpDQpgYGANCg0KIyMjIyBFYXN0L01pZHdlc3Qgey19DQoNCmBgYHtyfQ0KbWF0Y2h1cCgiRHVrZSIsICJIb3VzdG9uIikNCmBgYA0KDQojIyMjIFJlc3VsdHMgey19DQoNClRoZSBnYW1lIHdlIGdvdCB3cm9uZyBhbmQgaXRzIHJlc3BlY3RpdmUgV2luIFByb2JhYmlsaXR5Og0KDQoqICoqIzEqKiBEdWtlICg1NS42JSkgdnMgKiojMSoqIEhvdXN0b24gKDQ0LjQlKQ0KDQojIyMgTmF0aW9uYWwgQ2hhbXBpb25zaGlwIHstfQ0KDQpZb3UgbWF5IGhhdmUgbm90aWNlZCBieSBub3cgdGhhdCBlYWNoIHJvdW5kLCBJIGFtIHJlcGxhY2luZyB0aGUgcmVzdWx0cyB0aGF0IHdlIHByZWRpY3RlZCB3aXRoIHRoZSByZWFsLWxpZmUgb3V0Y29tZXMuIFVwIHRvIHRoaXMgcG9pbnQgaXQgd291bGRuJ3QgaGF2ZSBtYWRlIGEgZGlmZmVyZW5jZSBvdXRzaWRlIG9mIG9uZSBnYW1lLCAqKiMxMCoqIEFya2Fuc2FzIHZzICoqIzIqKiBTdC4gSm9obidzLiBFdmVyeSBvdGhlciB0ZWFtIHdlIGluY29ycmVjdGx5IGd1ZXNzZWQgd291bGQgbG9zZSwgYmVzaWRlcyBBcmthbnNhcywgd2VudCBvbiB0byBsb3NlIGluIHRoZSBuZXh0IHJvdW5kIGFuZCBkaWRuJ3QgY2hhbmdlIHRoZSBvdXRjb21lIG9mIHRoZSBTd2VldCBTaXh0ZWVuIGFuZCBFbGl0ZSBFaWdodC4gSG91c3RvbiwgaXJvbmljYWxseSwgaXMgbm90IGFuIGV4Y2VwdGlvbiB0byB0aGlzIHJ1bGUsIGRlc3BpdGUgb3VyIHByZWRpY3Rpb24gZ2l2aW5nIHRoZW0gYSBzbGlnaHQgZWRnZSBpbiB0aGlzIGZpbmFsLCBpbmNvcnJlY3QsIHJlc3VsdC4gSW4gcmVhbGl0eSwgRmxvcmlkYSBkZWZlYXRlZCBIb3VzdG9uIDY1LTYzIHRvIGNsYWltIHRoZSBOYXRpb25hbCBUaXRsZS4gDQoNCklmIHRoaXMgd2VyZSBuZXh0IHllYXIncyBicmFja2V0IGFuZCB3ZSBkaWRuJ3Qga25vdyBhbGwgb2YgdGhlIG91dGNvbWVzIHlldCwgaW5jb3JyZWN0bHkgZ3Vlc3NpbmcgdGhlIHdpbm5lciBvZiBib3RoIGEgRmluYWwgRm91ciBnYW1lICphbmQqIHRoZSBDaGFtcGlvbnNoaXAgd291bGQgYmUgYW4gaW5jcmVkaWJseSBwb29yIHdheSB0byBsb3NlIGEgcGVyZmVjdCBicmFja2V0LiBCdXQgdGhpcyBoaWdobGlnaHRzIGEgY29uY2VwdCB0aGF0IEknbGwgdG91Y2ggb24gbGF0ZXIgZGVzcGl0ZSBub3QgZnVsbHkgdW5kZXJzdGFuZGluZy4gQXMgdGhlIGZpZWxkIG5hcnJvd3MgYW5kIHRoZSBsZXZlbCBvZiBwbGF5IGluY3JlYXNlcywgb3VyIHByZWRpY3Rpb25zLCBpbiB0aGVvcnksIHNob3VsZCBiZSB3b3JzZS4gDQoNCmBgYHtyfQ0KbWF0Y2h1cCgiRmxvcmlkYSIsICJIb3VzdG9uIikNCmBgYA0KDQpUaGUgZ2FtZSB3ZSBnb3Qgd3JvbmcgYW5kIGl0cyByZXNwZWN0aXZlIFdpbiBQcm9iYWJpbGl0eTogDQoNCiogKiojMSoqIEZsb3JpZGEgKDQ3LjIlKSB2cyAqKiMxKiogSG91c3RvbiAoNTIuOCUpDQoNCiMgVGhlIFJlc3VsdHMNCg0KQmVmb3JlIHdlIGdldCBpbnRvIGdyYXBoaW5nIHRoZXNlIHRlYW1zIGFuZCB0cnlpbmcgdG8gY29tZSB1cCB3aXRoIHNvbWUgY2x1ZXMgdGhhdCBtYXkgaGF2ZSBwcmV2ZW50ZWQgb3VyIGJyYWNrZXQgZnJvbSBidXN0aW5nIG9uIHRoZSB2ZXJ5IGZpcnN0IGdhbWUgb2YgdGhlIFJvdW5kIG9mIDY0IChMb3Vpc3ZpbGxlIHZzIENyZWlnaHRvbiksIGxldCdzIGp1c3QgdGFrZSBhIGxvb2sgYXQgYWxsIG9mIHRoZSBtYXRjaHVwcyB3ZSBnb3QgaW5jb3JyZWN0bHkgaW4gb25lIHBsYWNlLiBPZiBteSA1Ni82NyByZXN1bHRzLCBoZXJlIGFyZSBhbGwgMTEgaW5jb3JyZWN0IHByZWRpY3Rpb25zLiANCg0KX19Sb3VuZCBvZiA2NF9fDQoNCiogKiojOCoqIExvdWlzdmlsbGUgKDY0LjclKSB2cyAqKiM5KiogQ3JlaWdodG9uICgzNS4zJSkNCg0KKiAqKiM3KiogTWFycXVldHRlICg2My44JSkgdnMgKiojMTAqKiBOZXcgTWV4aWNvICgzNi4yJSkNCg0KKiAqKiM2KiogTWlzc291cmkgKDc4LjglKSB2cyAqKiMxMSoqIERyYWtlICgyMS4yJSkNCg0KKiAqKiM3KiogS2Fuc2FzICg2OC40JSkgdnMgKiojMTAqKiBBcmthbnNhcyAoMzEuNiUpDQoNCiogKiojNSoqIENsZW1zb24gKDgwLjglKSB2cyAqKiMxMioqIE1jTmVlc2UgKDE5LjIlKQ0KDQpfX1JvdW5kIG9mIDMyX18NCg0KKiAqKiM1KiogTWljaGlnYW4gKDQzLjIlKSB2cyAqKiM0KiogVGV4YXMgQSZNICg1Ni44JSkNCg0KKiAqKiM2KiogT2xlIE1pc3MgKDMyLjclKSB2cyAqKiMzKiogSW93YSBTdC4gKDY3LjMlKQ0KDQoqICoqIzEwKiogQXJrYW5zYXMgKDIxLjIlKSB2cyAqKiMyKiogU3QuIEpvaG4ncyAoNzguOCUpDQoNCiogKiojNioqIEJZVSAoMzQuOSUpIHZzICoqIzMqKiBXaXNjb25zaW4gKDY1LjElKQ0KDQpfX0ZpbmFsIEZvdXJfXw0KDQoqICoqIzEqKiBEdWtlICg1NS42JSkgdnMgKiojMSoqIEhvdXN0b24gKDQ0LjQlKQ0KDQpfX05hdGlvbmFsIENoYW1waW9uc2hpcF9fDQoNCiogKiojMSoqIEZsb3JpZGEgKDQ3LjIlKSB2cyAqKiMxKiogSG91c3RvbiAoNTIuOCUpDQoNCjxicj4NCg0KV2UgY2FuIHNlZSB0aGF0IGFzIHdlIGdldCBjbG9zZXIgdG8gdGhlIENoYW1waW9uc2hpcCwgYW5kIHRoZW4gaW4gdGhlIENoYW1waW9uc2hpcCBpdHNlbGYsIHRoZSBsZXZlbCBvZiBjb21wZXRpdGlvbiBnZXRzIG11Y2ggbW9yZSBldmVuLiBPdXIgd2luIHByb2JhYmlsaXRpZXMgYW1vdW50IHRvIGVzc2VudGlhbGx5IGEgY29pbiBmbGlwLCBlc3BlY2lhbGx5IHdoZW4gY29uc2lkZXJpbmcgdGhhdCB0aGUgKnNjb3Jlcyogb2YgZWFjaCBnYW1lIGFmdGVyIHRoZSBFbGl0ZSBFaWdodCBpcyBwcmVkaWN0ZWQgdG8gYmUgd2l0aGluIDEgcG9pbnQuIE5vbmUgb2YgdGhlIGdhbWVzIGFjdHVhbGx5IGVuZGVkIGluIHN1Y2ggYSBuYXJyb3cgbWFyZ2luLCBidXQgYm90aCBvZiB0aGUgZ2FtZXMgdGhhdCB3ZSBwcmVkaWN0ZWQgaW5jb3JyZWN0bHkgKndlcmUqIGRlY2lkZWQgYnkgb25lIHBvc3Nlc3Npb24uIFRoZSBvbmx5IGdhbWUgd2UgZ290IGNvcnJlY3QgKEF1YnVybiB2cyBGbG9yaWRhKSB3YXMgZGVjaWRlZCBieSA2IHBvaW50cywgb3IganVzdCB0d28gcG9zc2Vzc2lvbnMuDQoNCkdldHRpbmcgYWxsIG9mIHRoZSBTd2VldCBTaXh0ZWVuIGFuZCBFbGl0ZSBFaWdodCBnYW1lcyBjb3JyZWN0IGFzIHRoZSBjb21wZXRpdGlvbiBuYXJyb3dzIGlzIGEgcmVzdWx0IEknbSBjb250ZW50IHdpdGgsIGJ1dCBkb2Vzbid0IHNlcnZlIHVzIHRvbyBtdWNoIHVzZWZ1bCBpbmZvcm1hdGlvbi4gSW4gZmFjdCwgb3V0IG9mIGFsbCB0d2VsdmUgZ2FtZXMgcGxheWVkIGluIHRob3NlIHJvdW5kcyB0aGF0IHdlIGdvdCBjb3JyZWN0LCBvbmx5IHRocmVlIG9mIHRoZW0gZW5kZWQgd2l0aGluIG9uZSBwb3NzZXNzaW9uLiBSZWFsaXN0aWNhbGx5LCB0aGVyZSdzIGFuIGVsZW1lbnQgb2YgbHVjayB3aGVuIGl0IGNvbWVzIHRvIGRlY2lkaW5nIHdoaWNoIHRlYW0gd2lsbCB3aW4gdGhlc2UgY29pbiBmbGlwIGdhbWVzIGlmIHdlIGdvIHN0cmljdGx5IGJ5IHRoZSBzY29yZSBwcmVkaWN0aW9ucywgYW5kIG5vdCBzb21lIG90aGVyIG1ldHJpYy4gDQoNCk9uIHRoZSBvdGhlciBlbmQgb2YgdGhlIHNwZWN0cnVtLCBhcmUgdGhlIHRydWUgdXBzZXRzIC0gdGhlIGJlZ2lubmluZ3Mgb2YgYSBDaW5kZXJlbGxhIFN0b3J5LiBXaGlsZSAyMDI1J3MgYnJhY2tldCBmZWF0dXJlZCByZWxhdGl2ZWx5IGxpdHRsZSBjaGFvcywgdGhlcmUgYXJlIHR3byB0ZWFtcyB0aGF0IHN0YW5kIG91dCBmcm9tIHRoZSBjcm93ZCBpbiBvdXIgZ3JvdXAgb2YgaW5jb3JyZWN0IHByZWRpY3Rpb25zIGFib3ZlLiBUaGUgZmlyc3QsIHdobyBoYXMgYmVlbiBtZW50aW9uZWQgb24gbW9yZSB0aGFuIG9uZSBvY2Nhc2lvbiBhbHJlYWR5LCB0aGUgKipBcmthbnNhcyBSYXpvcmJhY2tzKiouIFRoZSBvbmx5IGRvdWJsZS1kaWdpdCBzZWVkIHRvIG1ha2UgaXQgdG8gdGhlIFN3ZWV0IFNpeHRlZW4gd2l0aCByZWxhdGl2ZWx5IG1vZGVzdCwgYnV0IHJlc3BlY3RhYmxlIHN0YXRzLCB0aGUgUmF6b3JiYWNrcyB3ZXJlbid0IG5lY2Vzc2FyaWx5IGEgcHJvdG90eXBpY2FsIENpbmRlcmVsbGEgdGVhbS4gQnkgdmlydHVlIG9mIHBsYXlpbmcgaW4gdGhlIFNFQywgd2hpY2ggbWFueSBjb25zaWRlcmVkIHRvIGJlIHRoZSBzdHJvbmdlc3QgY29uZmVyZW5jZSBpbiB0aGUgbmF0aW9uIGxhc3QgeWVhciwgdGhleSBjYXJyaWVkIGEgbG90IG1vcmUgdGFsZW50IHRoYW4gdGhlaXIgc2VlZGluZyBtaWdodCBzdWdnZXN0LiBIb3dldmVyLCB3ZSB3ZXJlIHN0aWxsIHVuYWJsZSB0byBwcmVkaWN0IGVpdGhlciBvZiB0aGVpciB1cHNldCB3aW5zIGNvcnJlY3RseS4NCg0KVGhlIG90aGVyIG5vdGFibGUgdGVhbSwgb3duZXJzIG9mIHRoZSBsYXJnZXN0IHVwc2V0IHZpY3RvcnkgdGhyb3VnaG91dCB0aGUgZW50aXJlIHRvdXJuYW1lbnQgLSB0aGUgKipNY05lZXNlIENvd2JveXMqKi4gVGhpcyByZXN1bHQgaGl0cyBwYXJ0aWN1bGFybHkgY2xvc2UgdG8gaG9tZSwgYXMgaXQgY2FtZSBhdCB0aGUgY29uc2VxdWVuY2Ugb2YgYW4gZWFybHkgZXhpdCBmb3IgbXkgb3duIENsZW1zb24gVGlnZXJzLiBJIHdpbGwgcmVmcmFpbiBmcm9tIG1ha2luZyBhbnkgYmlhc2VkIGNvbW1lbnRzIG9yIGFzc3VtcHRpb25zIGFib3V0IHRoZSBvdXRjb21lIG9mIHRoYXQgZ2FtZSB0aGF0IGNhbid0IGJlIHZlcmlmaWVkIGJ5IHRoZSBkYXRhIEkgaGF2ZSBpbiBmcm9udCBvZiBtZSwgYW5kIHdpbGwgaW5zdGVhZCBvcHQgdG8gY3JlZGl0IHRoZSB1bmV4cGVjdGVkIGxvc3MgdG8gYW4gaW5qdXJ5IHN1ZmZlcmVkIGJ5IENsZW1zb24gZ3VhcmQgRGlsbG9uIEh1bnRlciBkdXJpbmcgdGhlIEFDQyBUb3VybmFtZW50Lg0KDQpUaGUgcmVzdCBvZiB0aGUgaW5jb3JyZWN0IGd1ZXNzZXMgdGVuZCB0byBmYWxsIGluIHRoZSByYW5nZSBvZiBhcm91bmQgYSAzMC00NSUgd2luIHByb2JhYmlsaXR5IHBlcmNlbnRhZ2UgZm9yIHRoZSB1bmRlcmRvZ3MuIFRoZXNlIGFyZSByZXN1bHRzIHRoYXQgbGlrZWx5IGNvdWxkIGhhdmUgZ29uZSBlaXRoZXIgd2F5LCBidXQgd2l0aG91dCBpbnZlc3RpZ2F0aW5nIHRoZW0gZnVydGhlciB3ZSdyZSBsZWZ0IHZpY3RpbXMgb2YgY2hhbmNlLiBJbiBvcmRlciB0byB0cnkgYW5kIGdhcm5lciBzb21lIGluc2lnaHQsIEknbGwgZXhwbG9yZSBzb21lIG9mIHRoZSBzdGF0aXN0aWNzIHdlIGhhdmUgYXQgb3VyIGRpc3Bvc2FsIHRvIHNlZSBpZiB0aGVyZSdzIGEgZGlzY3JlcGFuY3kgYmV0d2VlbiBvdXIgIkNpbmRlcmVsbGFzIiBhbmQgb3VyIHByb3ZlcmJpYWwgInN0ZXBzaXN0ZXJzLiINCg0KIyBUaGUgR2xhc3MgU2xpcHBlciAtIFdoYXQgU2V0cyBUZWFtcyBBcGFydD8NCg0KV2UnbGwgZmlyc3Qgc3RhcnQgYnkgY3JlYXRpbmcgYSBzdWJzZXQgb2YgdGhlIHRlYW1zIHRoYXQgcHVsbGVkIG9mZiBhbiAidXBzZXQiIGdpdmVuIG91ciBwcmVkaWN0aW9ucywgYW5kIGEgc2VwYXJhdGUgc3Vic2V0IG9mIHRoZSB0ZWFtcyB3aG8gbG9zdCB0byB0aGVtLiBUaGF0IHdheSwgd2UgY2FuIGhpZ2hsaWdodCBlYWNoIGFuZCBzZWUgaWYgdGhlcmUncyBhbnkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgdHdvIGdyb3Vwcy4NCg0KPGJyPg0KDQpgYGB7ciwgZmlnLnNob3c9J2hvbGQnLCBvdXQud2lkdGg9IjUwJSIsIHdhcm5pbmc9RkFMU0V9DQojIEZpbHRlcnMgb3V0IGp1c3Qgb3VyICJ1bmRlcmRvZ3MiDQp1bmRlcnMgPC0gc3RhdHMyIHw+DQogIGZpbHRlcih0ZWFtICVpbiUgYygiQ3JlaWdodG9uIiwgIk5ldyBNZXhpY28iLCAiRHJha2UiLCAiQXJrYW5zYXMiLCAiTWNOZWVzZSIsICJNaWNoaWdhbiIsICJPbGUgTWlzcyIsICJCWVUiLCAiSG91c3RvbiIsICJGbG9yaWRhIikpDQoNCiMgRmlsdGVycyBvdXQganVzdCB0aGUgdGVhbXMgb3VyICJ1bmRlcmRvZ3MiIGxvc3QgdG8NCnVwc2V0cyA8LSBzdGF0czIgfD4NCiAgZmlsdGVyKHRlYW0gJWluJSBjKCJMb3Vpc3ZpbGxlIiwgIk1hcnF1ZXR0ZSIsICJNaXNzb3VyaSIsICJLYW5zYXMiLCAiQ2xlbXNvbiIsICJUZXhhcyBBJk0iLCAiSW93YSBTdC4iLCAiU3QuIEpvaG4ncyAoTlkpIiwgIldpc2NvbnNpbiIsICJEdWtlIiwgIkhvdXN0b24iKSkNCg0KZ2dwbG90KHN0YXRzMiwgYWVzKHggPSBlRkcsIHkgPSBvcHAuZUZHKSkrDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW4oc3RhdHMyJGVGRyksIGNvbG9yID0gImJsYWNrIikrDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IG1lYW4oc3RhdHMyJG9wcC5lRkcpLCBjb2xvciA9ICJibGFjayIpKw0KICBnZW9tX2NiYl90ZWFtcyhkYXRhID0gc3RhdHMyLCBhZXModGVhbSA9IHRlYW0pLCB3aWR0aCA9IDAuMDUsIHNob3cubGVnZW5kID0gRkFMU0UpKw0KICBnZ2hpZ2hsaWdodCh0ZWFtICVpbiUgYygiQ3JlaWdodG9uIiwgIk5ldyBNZXhpY28iLCAiRHJha2UiLCAiQXJrYW5zYXMiLCAiTWNOZWVzZSIsICJNaWNoaWdhbiIsICJPbGUgTWlzcyIsICJCWVUiLCAiSG91c3RvbiIsICJGbG9yaWRhIikpKw0KICB4bGltKG1pbihzdGF0czIkZUZHKSwgbWF4KHN0YXRzMiRlRkcpKSsNCiAgeWxpbShtaW4oc3RhdHMyJG9wcC5lRkcpLCBtYXgoc3RhdHMyJG9wcC5lRkcpKSsNCiAgbGFicyh4ID0gIlRlYW0gZUZHJSIsDQogICAgICAgeSA9ICJPcHBvbmVudCBlRkclIiwNCiAgICAgICB0aXRsZSA9ICdUZWFtIGVGRyUgdnMuIE9wcG9uZW50IGVGRyUgZm9yICJVbmRlcmRvZyIgVGVhbXMnKQ0KDQpnZ3Bsb3Qoc3RhdHMyLCBhZXMoeCA9IGVGRywgeSA9IG9wcC5lRkcpKSsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVhbihzdGF0czIkZUZHKSwgY29sb3IgPSAiYmxhY2siKSsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWVhbihzdGF0czIkb3BwLmVGRyksIGNvbG9yID0gImJsYWNrIikrDQogIGdlb21fY2JiX3RlYW1zKGRhdGEgPSBzdGF0czIsIGFlcyh0ZWFtID0gdGVhbSksIHdpZHRoPTAuMDUsIHNob3cubGVnZW5kID0gRkFMU0UpKw0KICBnZ2hpZ2hsaWdodCh0ZWFtICVpbiUgYygiTG91aXN2aWxsZSIsICJNYXJxdWV0dGUiLCAiTWlzc291cmkiLCAiS2Fuc2FzIiwgIkNsZW1zb24iLCAiVGV4YXMgQSZNIiwgIklvd2EgU3QuIiwgIlN0LiBKb2huJ3MgKE5ZKSIsICJXaXNjb25zaW4iLCAiRHVrZSIsICJIb3VzdG9uIikpKw0KICB4bGltKG1pbihzdGF0czIkZUZHKSwgbWF4KHN0YXRzMiRlRkcpKSsNCiAgeWxpbShtaW4oc3RhdHMyJG9wcC5lRkcpLCBtYXgoc3RhdHMyJG9wcC5lRkcpKSsNCiAgbGFicyh4ID0gIlRlYW0gZUZHJSIsDQogICAgICAgeSA9ICJPcHBvbmVudCBlRkclIiwNCiAgICAgICB0aXRsZSA9ICdUZWFtIGVGRyUgdnMuIE9wcG9uZW50IGVGRyUgZm9yIFRlYW1zIFdobyBXZXJlICJVcHNldCInKQ0KYGBgDQoNCjxicj4NCg0KSGVyZSB3ZSBnZXQgc29tZSBzbGlnaHQgaW5zaWdodCBhcyB0byB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGEgZmV3IG9mIHRoZXNlIHRlYW1zLCBidXQgZm9yIHRoZSBtb3N0IHBhcnQgdGhlIHJlc3VsdHMgYXJlIGluY29uY2x1c2l2ZS4gSW4gdGhpcyBwYXJ0aWN1bGFyIGdyYXBoLCB5b3Ugd2FudCB0byBiZSBpbiB0aGUgYm90dG9tIHJpZ2h0IHF1YWRyYW50IHdpdGggYSBoaWdoIGBlRkclYCwgYW5kIGEgbG93IGBvcHAuZUZHJWAuICBXZSBjYW4gc2VlIHRoYXQgdGVhbXMgbGlrZSAqKk1jTmVlc2UqKiwgKipDcmVpZ2h0b24qKiwgYW5kICoqTWljaGlnYW4qKiBmYXJlIGJldHRlciBpbiBib3RoIGBlRkclYCBhbmQgYG9wcC5lRkclYCB0aGFuIHRoZWlyIG9wcG9uZW50cywgYnV0IG1vcmUgb2Z0ZW4gdGhhbiBub3QgdGhlIHBhdHRlcm4gZG9lc24ndCBzZWVtIHRvIGhvbGQuIEl0J3Mgc3RpbGwgd29ydGggbm90aW5nIHRoYXQgc2l4IG9mIHRoZSB0ZWFtcyB3aG8gc3VmZmVyZWQgdXBzZXQgbG9zc2VzIGhhZCBhIGJlbG93IGF2ZXJhZ2UgYGVGRyVgLCBhbmQgQ2xlbXNvbiBpcyBqdXN0IHNpZ2h0bHkgYWJvdmUgYXZlcmFnZS4NCg0KPGJyPg0KDQpTaW5jZSBgZUZHJWAgYW5kIGBvcHAuZUZHJWAgYXJlbid0IG9wcG9uZW50LWFkanVzdGVkLCB3ZSBjYW4gdHJ5IHRvIGNvbXBhcmUgb3VyIG9wcG9uZW50LWFkanVzdGVkIGVmZmljaWVuY2llcyBhbmQgc2VlIGlmIHRoYXQgZ2l2ZXMgdXMgc29tZSBtb3JlIGluc2lnaHQuIEV2ZW4gdGhvdWdoIHRoaXMgZm9sbG93cyBvdXIgbWV0aG9kb2xvZ3kgZm9yIGZpbmRpbmcgb3VyIGV4cGVjdGVkIHNjb3JlcywgYW5kIGxpa2VseSB3b24ndCB0ZWxsIHVzIG11Y2gsIG9uZSBvciB0d28gb3V0bGllcnMgY291bGQgYmUgdGhlIGRpZmZlcmVuY2UgbWFrZXIgd2hlbiBkZWNpZGluZyB3aGljaCBvdGhlcndpc2UgZXZlbmx5LW1hdGNoZWQgdGVhbSB3ZSBzaG91bGQgcGljay4NCg0KYGBge3IsIGZpZy5zaG93PSdob2xkJywgb3V0LndpZHRoPSI1MCUiLCB3YXJuaW5nPUZBTFNFfQ0KZ2dwbG90KHN0YXRzMiwgYWVzKHggPSBPUnRnLCB5ID0gRFJ0ZykpKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuKHN0YXRzMiRPUnRnKSwgY29sb3IgPSAiYmxhY2siKSsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWVhbihzdGF0czIkRFJ0ZyksIGNvbG9yID0gImJsYWNrIikrDQogIGdlb21fY2JiX3RlYW1zKGRhdGEgPSBzdGF0czIsIGFlcyh0ZWFtID0gdGVhbSksIHdpZHRoPTAuMDUsIHNob3cubGVnZW5kID0gRkFMU0UpKw0KICBnZ2hpZ2hsaWdodCh0ZWFtICVpbiUgYygiQ3JlaWdodG9uIiwgIk5ldyBNZXhpY28iLCAiRHJha2UiLCAiQXJrYW5zYXMiLCAiTWNOZWVzZSIsICJNaWNoaWdhbiIsICJPbGUgTWlzcyIsICJCWVUiLCAiSG91c3RvbiIsICJGbG9yaWRhIikpKw0KICB4bGltKG1pbihzdGF0czIkT1J0ZyksIG1heChzdGF0czIkT1J0ZykpKw0KICB5bGltKG1pbihzdGF0czIkRFJ0ZyksIG1heChzdGF0czIkRFJ0ZykpKw0KICBsYWJzKHggPSAiVGVhbSBPUnRnIiwNCiAgICAgICB5ID0gIlRlYW0gRFJ0ZyIsDQogICAgICAgdGl0bGUgPSAnVGVhbSBPUnRnIHZzLiBUZWFtIERSdGcgZm9yICJVbmRlcmRvZyIgVGVhbXMnKQ0KDQpnZ3Bsb3Qoc3RhdHMyLCBhZXMoeCA9IE9SdGcsIHkgPSBEUnRnKSkrDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW4oc3RhdHMyJE9SdGcpLCBjb2xvciA9ICJibGFjayIpKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBtZWFuKHN0YXRzMiREUnRnKSwgY29sb3IgPSAiYmxhY2siKSsNCiAgZ2VvbV9jYmJfdGVhbXMoZGF0YSA9IHN0YXRzMiwgYWVzKHRlYW0gPSB0ZWFtKSwgd2lkdGg9MC4wNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkrDQogIGdnaGlnaGxpZ2h0KHRlYW0gJWluJSBjKCJMb3Vpc3ZpbGxlIiwgIk1hcnF1ZXR0ZSIsICJNaXNzb3VyaSIsICJLYW5zYXMiLCAiQ2xlbXNvbiIsICJUZXhhcyBBJk0iLCAiSW93YSBTdC4iLCAiU3QuIEpvaG4ncyAoTlkpIiwgIldpc2NvbnNpbiIsICJEdWtlIiwgIkhvdXN0b24iKSkrDQogIHhsaW0obWluKHN0YXRzMiRPUnRnKSwgbWF4KHN0YXRzMiRPUnRnKSkrDQogIHlsaW0obWluKHN0YXRzMiREUnRnKSwgbWF4KHN0YXRzMiREUnRnKSkrDQogIGxhYnMoeCA9ICJUZWFtIE9SdGciLA0KICAgICAgIHkgPSAiVGVhbSBEUnRnIiwNCiAgICAgICB0aXRsZSA9ICdUZWFtIE9SdGcgdnMuIFRlYW0gRFJ0ZyBmb3IgVGVhbXMgV2hvIFdlcmUgIlVwc2V0IicpDQpgYGANCg0KPGJyPg0KDQpBcyBleHBlY3RlZCwgdGhpcyBncmFwaCBkb2Vzbid0IHRlbGwgdXMgYWxsIHRvbyBtdWNoIGVpdGhlci4gVGhlIG9ubHkgcmVhbCBpbnNpZ2h0IGhlcmUgbWlnaHQgYmUgdGhhdCBnaXZlbiB0aGUgY2x1c3RlcmluZyBvZiB0aGUgdGVhbXMgd2hvIGZhY2VkIHVwc2V0cywgdGhlIG9uZXMgd2hvIGxvc3QgaW4gdGhlIFJvdW5kIG9mIDY0IGFuZCBSb3VuZCBvZiAzMiBkb24ndCBkbyBhbnl0aGluZyBleGNlcHRpb25hbGx5IHdlbGwuIFRoZXkncmUgYWJvdmUgYXZlcmFnZSBpbiBvZmZlbnNpdmUgYW5kIGRlZmVuc2l2ZSBlZmZpY2llbmN5LCBidXQgdGhleSBhcmVuJ3QgaW1tdW5lIHRvIGxvc2luZyBhIGJhc2tldGJhbGwgZ2FtZS4gVGhlIG90aGVyIHRlYW1zIGFsbCB0aGUgd2F5IG91dCBvbiB0aGUgcmlnaHQgZW5kIG9mIHRoZSBncmFwaCB3aXRoIER1a2UgaW4gYE9SdGdgIGFyZSBGbG9yaWRhLCB3aG8gd291bGQgZXZlbnR1YWxseSBnbyBvbiB0byB3aW4gdGhlIFRvdXJuYW1lbnQsIGFuZCBBdWJ1cm4sIHdobyBsb3N0IHRvIEZsb3JpZGEgaW4gdGhlIEZpbmFsIEZvdXIuIA0KDQpUaGUgdGVhbSBjbG9zZXN0IHRvIEhvdXN0b24gb24gdGhpcyBncmFwaD8gVGVubmVzc2VlLiBXaG8gdGhleSBkZWZlYXRlZCBpbiB0aGUgRWxpdGUgRWlnaHQuIEkgdGhpbmsgaXQncyBub3QgdW5yZWFzb25hYmxlIHRvIHNheSB0aGF0ICp0aGVzZSogdGVhbXMgKmFyZSogc29tZXdoYXQgaW1tdW5lIHRvIHVwc2V0cywgYWxsIHRoZSB3YXkgZG93biBpbiB0aGUgYm90dG9tIHJpZ2h0IG9mIHRoZSBncmFwaC4gVGVhbXMgbGlrZSBTdC4gSm9obidzIGFuZCBNaXNzb3VyaSB0aG91Z2gsIHdobyBleGNlbCBvbiBvbmUgZW5kIG9mIHRoZSBjb3VydCBhbmQgYXJlIHJlbGF0aXZlbHkgcGVkZXN0cmlhbiBvbiB0aGUgb3RoZXIsIGRvbid0IHNoYXJlIHRoYXQgbHV4dXJ5Lg0KDQo8YnI+IA0KDQpXZSd2ZSBkZXRlcm1pbmVkIHRoYXQgc2NvcmluZyBlZmZpY2llbmN5IG1hdHRlcnMgdG8gc29tZSBleHRlbnQsIGFzIGRvZXMgdGhlIGFtb3VudCBlYWNoIHRlYW0gc2NvcmVzIHBlciBzaG90LiBMZXQncyB0YWtlIHRob3NlIGNvbmNlcHRzIG5vdywgYW5kIGxvb2sgdG8gc2VlIGlmIHRoZXNlIHRlYW1zIGZpdCBpbnRvIGVpdGhlciBvZiB0aGUgInRlYW0gaWRlbnRpdGllcyIgd2UgbWVudGlvbmVkIGVhcmxpZXIuIEFjcm9zcyB0aGUgc3BvcnQgb2YgYmFza2V0YmFsbCwgdGhlIHRocmVlLXBvaW50ZXIgaGFzIGNvbXBsZXRlbHkgcmVzaGFwZWQgdGhlIHNjb3JpbmcgbGFuZHNjYXBlLiBQZXJoYXBzIHdlIGNhbiBzZWUgaWYgdGhlcmUncyBhIGRpc2NyZXBhbmN5IGJldHdlZW4gdGhlIHNsb3dlciwgbW9yZSBtZXRob2RpY2FsIHRlYW1zIHdobyB0cnkgdG8gY3JhZnQgdGhlIHBlcmZlY3Qgc2hvdCwgYW5kIHRoZSBtb3JlICJydW4gYW5kIGd1biIgc3R5bGUgb2YgcGxheS4gDQoNCmBgYHtyLCBmaWcuc2hvdz0naG9sZCcsIG91dC53aWR0aD0iNTAlIiwgd2FybmluZz1GQUxTRX0NCmdncGxvdChzdGF0czIsIGFlcyh4ID0gQWRqVCwgeSA9IHRocmVlcC5wZXJjLm9mZikpKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuKHN0YXRzMiRBZGpUKSwgY29sb3IgPSAiYmxhY2siKSsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbWVhbihzdGF0czIkdGhyZWVwLnBlcmMub2ZmKSwgY29sb3IgPSAiYmxhY2siKSsNCiAgZ2VvbV9jYmJfdGVhbXMoZGF0YSA9IHN0YXRzMiwgYWVzKHRlYW0gPSB0ZWFtKSwgd2lkdGg9MC4wNSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkrDQogIGdnaGlnaGxpZ2h0KHRlYW0gJWluJSBjKCJDcmVpZ2h0b24iLCAiTmV3IE1leGljbyIsICJEcmFrZSIsICJBcmthbnNhcyIsICJNY05lZXNlIiwgIk1pY2hpZ2FuIiwgIk9sZSBNaXNzIiwgIkJZVSIsICJIb3VzdG9uIiwgIkZsb3JpZGEiKSkrDQogIHhsaW0obWluKHN0YXRzMiRBZGpUKSwgbWF4KHN0YXRzMiRBZGpUKSkrDQogIHlsaW0obWluKHN0YXRzMiR0aHJlZXAucGVyYy5vZmYpLCBtYXgoc3RhdHMyJHRocmVlcC5wZXJjLm9mZikpKw0KICBsYWJzKHggPSAiVGVhbSBBZGpUIiwNCiAgICAgICB5ID0gIlRlYW0gM1AlIiwNCiAgICAgICB0aXRsZSA9ICdUZWFtIEFkalQgdnMuIFRlYW0gM1AlIGZvciAiVW5kZXJkb2ciIFRlYW1zJykNCg0KZ2dwbG90KHN0YXRzMiwgYWVzKHggPSBBZGpULCB5ID0gdGhyZWVwLnBlcmMub2ZmKSkrDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lYW4oc3RhdHMyJEFkalQpLCBjb2xvciA9ICJibGFjayIpKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBtZWFuKHN0YXRzMiR0aHJlZXAucGVyYy5vZmYpLCBjb2xvciA9ICJibGFjayIpKw0KICBnZW9tX2NiYl90ZWFtcyhkYXRhID0gc3RhdHMyLCBhZXModGVhbSA9IHRlYW0pLCB3aWR0aD0wLjA1LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSsNCiAgZ2doaWdobGlnaHQodGVhbSAlaW4lIGMoIkxvdWlzdmlsbGUiLCAiTWFycXVldHRlIiwgIk1pc3NvdXJpIiwgIkthbnNhcyIsICJDbGVtc29uIiwgIlRleGFzIEEmTSIsICJJb3dhIFN0LiIsICJTdC4gSm9obidzIChOWSkiLCAiV2lzY29uc2luIiwgIkR1a2UiLCAiSG91c3RvbiIpKSsNCiAgeGxpbShtaW4oc3RhdHMyJEFkalQpLCBtYXgoc3RhdHMyJEFkalQpKSsNCiAgeWxpbShtaW4oc3RhdHMyJHRocmVlcC5wZXJjLm9mZiksIG1heChzdGF0czIkdGhyZWVwLnBlcmMub2ZmKSkrDQogIGxhYnMoeCA9ICJUZWFtIEFkalQiLA0KICAgICAgIHkgPSAiVGVhbSAzUCUiLA0KICAgICAgIHRpdGxlID0gJ1RlYW0gQWRqVCB2cy4gVGVhbSAzUCUgZm9yIFRlYW1zIFdobyBXZXJlICJVcHNldCInKQ0KYGBgDQoNCjxicj4NCg0KUmlnaHQgb2ZmIHRoZSBiYXQsIHRoaXMgZ3JhcGggZ2l2ZXMgdXMgYW4gZXhjZWxsZW50IGxvb2sgYXQgYSBjb3VwbGUgbWF0Y2h1cC1zcGVjaWZpYyBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRlYW1zLiBXZSBjYW4gc2VlIGEgZmV3IGNsZWFyIHRyZW5kcyByaWdodCBhd2F5LCB0aGF0IHNlZW0gdG8gaG9sZCB3aXRoIG91ciBlYXJsaWVyIGFzc3VtcHRpb25zLiBUaGUgZmlyc3Qgb2YgdGhlc2UgaXMgdGhhdCBoaWdoLXRlbXBvIHRlYW1zIHN0cnVnZ2xlIGFnYWluc3QgbG93IHRlbXBvIHRlYW1zLiBUaGlzIHdhcyBhIGNvbmNlcHQgSSBnZW5lcmFsbHkgZ3Jhc3BlZCBhbmQgaGFkIGJyb3VnaHQgdXAgYWxyZWFkeSwgYnV0IG5vdyB3ZSBjYW4gc2VlIGNsZWFybHkganVzdCBob3cgYmlnIG9mIGFuIGltcGFjdCBpdCBjYW4gaGF2ZS4gIzExIERyYWtlIHBsYXlzIGF0IGFuIGFic29sdXRlbHkgZ2xhY2lhbCBwYWNlLCBhdmVyYWdpbmcganVzdCA1OC44IHBvc3Nlc3Npb25zIHBlciBnYW1lLiBUaGV5J3JlIHRoZSBzbG93ZXN0IHRlYW0gaW4gdGhlIGNvdW50cnksIGFuZCB0aGF0IGNoYW5nZSBvZiBwYWNlIHdhcyBlbm91Z2ggZm9yIHRoZW0gdG8gdG9wcGxlIGEgZmFzdCBNaXNzb3VyaSB0ZWFtIHdobyBjb3VsZG4ndCBhZGp1c3QgdG8gZXNzZW50aWFsbHkgd2Fsa2luZyB1cCBhbmQgZG93biB0aGUgY291cnQuIFVuZm9ydHVuYXRlbHkgZm9yIERyYWtlLCB0aGV5IHJhbiBpbnRvIFRleGFzIFRlY2ggaW4gdGhlIFJvdW5kIG9mIDMyICh0aGUgcG9pbnQgb24gdGhlIGdyYXBoIHJpZ2h0IGFib3ZlIER1a2UpLiBUZXhhcyBUZWNoIGlzIGNvbWZvcnRhYmxlIHBsYXlpbmcgYXQgYSBzbG93ZXIgdGhhbiBhdmVyYWdlIHRlbXBvLCBhbmQgc2hvb3RzIG11Y2ggbW9yZSBlZmZpY2llbnRseSB0aGFuIERyYWtlLCBhdCBhIGhpZ2hlciB2b2x1bWUuIEZvciB0ZWFtcyB0aGF0IHBsYXkgYXQgYSBzaW1pbGFyIHRlbXBvLCB3aXRoaW4gMi0zIHBvc3Nlc3Npb25zIHBlciBnYW1lLCB0aGUgbW9yZSBlZmZpY2llbnQgdGVhbXMgYWxtb3N0IGFsd2F5cyB3aW4uIA0KDQpUaGVyZSBhcmUgb25seSB0aHJlZSBleGNlcHRpb25zIHRvIHRoaXMgcnVsZSBpbiBvdXIgcGxvdCwgb25lIG9mIHdoaWNoIHdlIGFscmVhZHkgZGVlbWVkIGEgY29pbiBmbGlwIGVhcmxpZXIgaW4gIzEgSG91c3RvbiB2cyAjMSBGbG9yaWRhLiBDb2luY2lkZW50YWxseSwgdGhvc2UgdHdvIGV4Y2VwdGlvbnMgYXJlIG91ciAiQ2luZGVyZWxsYSIgdGVhbXMuICoqT3Igc28gaXQgbWF5IHNlZW0uKiogQWxvbmcgd2l0aCBDbGVtc29uLCB3aG8gd2FzIHdpdGhvdXQgRGlsbG9uIEh1bnRlciBpbiB0aGVpciBmaXJzdCBhbmQgb25seSBnYW1lIGluIHRoZSB0b3VybmFtZW50LCBLYW5zYXMgd2FzIGFsc28gcGxheWluZyBzaG9ydGhhbmRlZC4gQnJpZWZseS4gTGVhZGluZyA2Ny02NCBvdmVyIEFya2Fuc2FzIHdpdGggMzoxMCBvbiB0aGUgY2xvY2ssIEpheWhhd2tzJyBzdGFyIGZvcndhcmQgS0ogQWRhbXMgdG9yZSBoaXMgYWNoaWxsZXMgYW5kIHdhcyBmb3JjZWQgdG8gbGVhdmUgdGhlIGdhbWUuIEluIHRoZSByZW1haW5pbmcgMyBtaW51dGVzIGFuZCAxMCBzZWNvbmRzIEFya2Fuc2FzIHdvdWxkIGdvIG9uIHRvIG91dHNjb3JlIEthbnNhcyAxNS01LCBjbG9zaW5nIG91dCB0aGUgZ2FtZSB3aXRoIGEgZmluYWwgc2NvcmUgb2YgNzktNzIgaW4gZmF2b3Igb2YgdGhlIFJhem9yYmFja3MuIE91dHNpZGUgb2YgdGhvc2UgdHdvIGluanVyeS1yZWxhdGVkIGFub21hbGllcywgYW5kIHRoZSBOYXRpb25hbCBDaGFtcGlvbnNoaXAgZ2FtZSwgb3VyIHJ1bGUgaG9sZHMgYWNyb3NzIGFsbCB0aGUgb3RoZXIgdXBzZXRzLiBXaGVuIHR3byBvdGhlcndpc2UgZXZlbmx5LW1hdGNoZWQgdGVhbXMgc3F1YXJlIG9mZiBhZ2FpbnN0IGVhY2ggb3RoZXIsIHRoZSB0ZWFtIHRoYXQncyBtb3JlIGVmZmljaWVudCBmcm9tIGJlaGluZCB0aGUgYXJjIGlzIGFsbW9zdCBhbHdheXMgZ29pbmcgdG8gd2luLiANCg0KWW91IGNhbiBpbnZlc3RpZ2F0ZSBhbGwgb2YgdGhpcyBmb3IgeW91cnNlbGYgdXNpbmcgdGhlIFtmbGV4ZGFzaGJvYXJkXShodHRwczovL2RpdmlkZW9uZS5zaGlueWFwcHMuaW8vZmxleGRhc2hib2FyZF9tbS8pIEkndmUgY3JlYXRlZCBmb3IgdGhpcyBkYXRhIGFzIHdlbGwuDQoNCiMgVGFrZWF3YXlzDQoNCk91ciB3aW4gcHJvYmFiaWxpdGllcyBnaXZlIHVzIGEgZ29vZCBpZGVhIG9mIGNsZWFyIHdpbm5lcnMuIEFueSB0ZWFtIHdpdGggYSA3MCUgY2hhbmNlIHRvIHdpbiBvciBiZXR0ZXIgd29uIGluIGFsbCBidXQgdGhyZWUgaW5zdGFuY2VzLiBUd28gb2YgdGhlc2Ugd2UgY2FuIGF0dHJpYnV0ZSB0byBpbmp1cmllcyBhZGRpbmcgYW4gZWxlbWVudCBvZiByYW5kb21uZXNzLCBhbmQgdGhlIHRoaXJkIHdlIGNhbiBhdHRyaWJ1dGUgdG8gYSAqdmFzdCogZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gdGVhbXMnIHNob290aW5nIGFiaWxpdHksIHdoaWNoIGlzIGp1c3QgcGFydCBvZiB0aGUgUmljayBQaXRpbm8gRXhwZXJpZW5jZS4gQW55IHRlYW0gd2l0aCBhIDMwJSBjaGFuY2UgdG8gd2luIG9yIGJldHRlciwgY2FuIHdpbi4gV2UgY2FuIGFsbW9zdCBwZXJmZWN0bHkgcHJlZGljdCB0aGUgb3V0Y29tZSBpbiB0aGVzZSBnYW1lcyBiYXNlZCBvbiB0d28gdGhpbmdzLiBUaGUgZmlyc3QgaXMgdGVtcG8sIG11Y2ggc2xvd2VyIHRlYW1zIGhvbGQgYW4gYWR2YW50YWdlIG92ZXIgdGVhbXMgdGhhdCBsaWtlIHRvIHBsYXkgZmFzdGVyIHRoYW4gYXZlcmFnZS4gVGhlIHNlY29uZCwgd2hlbiB0ZW1wbyBpcyBub3QgYSBxdWVzdGlvbiwgaXMgYDNQJWAuIFRlYW1zIHRoYXQgYXJlIGFibGUgdG8gc2NvcmUgdGhyZWVzIGF0IGEgaGlnaGVyIGNsaXAgdGhhbiB0aGVpciBvcHBvbmVudCBhbG1vc3QgYWx3YXlzIHdhbGsgYXdheSB3aXRoIGEgdmljdG9yeSBvdmVyIGxlc3MtZWZmaWNpZW50IHNob290aW5nLiBPdXIgbm90YWJsZSBleGNlcHRpb24gdG8gdGhpcyBpcyB0aGUgTmF0aW9uYWwgQ2hhbXBpb25zaGlwIGdhbWUsIHdoZXJlIHRoZSBiZXN0IG9mZmVuc2UgaW4gdGhlIGNvdW50cnkgZmFjZWQgb2ZmIGFnYWluc3QgdGhlIChzZWNvbmQpIGJlc3QgZGVmZW5zZSBpbiB0aGUgY291bnRyeS4gVGhlc2UgdGVhbXMgYXQgdGhlIHZlcnkgdG9wIG9mIG91ciBvZmZlbnNpdmUgYW5kIGRlZmVuc2l2ZSByYW5raW5ncyBzZWVtIHRvIGJlIGp1Z2dlcm5hdXRzIHdoZW4gbW92aW5nIHRocm91Z2ggYnJhY2tldCwgYW5kIHVudGlsIHRoZXkgbWVldCBhbiBvcHBvbmVudCB3aXRoIHNpbWlsYXIgYWJpbGl0eSwgdGhleSdyZSBnb2luZyB0byBlYXNpbHkgbWFrZSB0aGVpciB3YXkgdG93YXJkcyB0aGUgbGF0ZXIgcm91bmRzLiANCg0KSXQncyBpbXBvc3NpYmxlIHRvIHByZWRpY3QgaW5qdXJpZXMuIE5vIG1vZGVsIGNhbiBhY2NvdW50IGZvciB0aGF0IGV2ZW50IGluIHRoZSBtaWRkbGUgb2YgdGhlIHRvdXJuYW1lbnQuIEJ1dCB0aGF0J3MgdGhlIGJlYXV0eSBvZiBzb2x2aW5nIHRoZSAqTWFyY2ggTWFkbmVzcyogYnJhY2tldC4gU2ltcGx5IHB1dCwgbm9ib2R5IGtub3dzIHdoYXQncyBnb2luZyB0byBoYXBwZW4gYW5kIHRoZXJlJ3MgYW4gZWxlbWVudCBvZiByYW5kb21uZXNzIHRoYXQgY29tZXMgd2l0aCBtYWtpbmcgcGlja3MuIFNvbWUgbWF5IGV2ZW4gY2FsbCBpdCBsdWNrLiBJIHBvc2l0IHRoYXQgaWYgd2Ugd2VyZSB0byBsb29rIGF0IGV2ZXJ5IGluZGl2aWR1YWwgbWF0Y2h1cCBhbmQgYXBwbHkgb25seSB0aGUgcnVsZXMgY29tcGFyaW5nIGAzUCVgIHRvIGBBZGpUYCBpbiBjYXNlcyB3aGVyZSBjbG9zZWx5IG1hdGNoZWQgdGVhbXMgcGxheSBhdCBhIHNpbWlsYXIgc3BlZWQsIGFuZCBmYXZvcmluZyB0aGUgc2xvd2VyIHRlYW0gaWYgdGhleSBkb24ndCwgb3VyIGJyYWNrZXQgd291bGQgcHV0IHVwIHNvbWUgcmVhc29uYWJseSBzdWNjZXNzZnVsIHJlc3VsdHMuDQoNClJlZ2FyZGxlc3Mgb2YgdGhlIGluaGVyZW50IHJhbmRvbW5lc3MgdGhhdCBjb21lcyB3aXRoIGFueSBsaXZlIHNwb3J0aW5nIGV2ZW50LCB3ZSBjYW4gZGVmaW5pdGVseSBkcmF3IGEgbG90IG1vcmUgaW5zaWdodHMgZnJvbSB0aGlzIGFwcHJvYWNoIHRoYW4gSSBiZWdhbiB3aXRoLiBCeSBhcHBseWluZyB0aGlzIGNvbmNlcHQgb2YgInRlYW0gaWRlbnRpdGllcywiIHJhdGhlciB0aGFuIGJsaW5kbHkgZm9sbG93aW5nIGEgc2NvcmUgcHJlZGljdGlvbiwgSSB3b3VsZG4ndCBiZSBzdXJwcmlzZWQgaWYgdGhpcyBtb2RlbCwgd2hlbiBhcHBsaWVkIHdpdGggYSBuZXcsIGRlZXBlciB1bmRlcnN0YW5kaW5nIG9mIHRlYW0gbWF0Y2h1cHMsIHNlZXMgdXB3YXJkcyBvZiA2MC82NyBjb3JyZWN0IHBpY2tzLg0KDQpUaGVyZSdzIDQwIGRpZmZlcmVudCB2YXJpYWJsZXMgLSBzb21lIG1vcmUgaW1wb3J0YW50IHRoYW4gb3RoZXJzIC0gaW4gdGhpcyBkYXRhc2V0LiBJIGNvdWxkIHNpdCBoZXJlIGZvciB0aGUgbmV4dCBmZXcgbW9udGhzIG9mIG15IGxpZmUgaW52ZXN0aWdhdGluZyBlYWNoLCBidWlsZGluZyBhIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBhbGwgNDAgYW5kIHRyeWluZyB0byBmaXQgaXQgcGVyZmVjdGx5LiBBdCB0aGUgZW5kIG9mIHRoZSBkYXksIG5vdGhpbmcncyBnb2luZyB0byBhY2NvdW50IGZvciB0aGUgcmFuZG9tbmVzcy4gSW4gZmFjdCwgYW1vbmcgbXkgZnJpZW5kIGdyb3VwLCBkZXNwaXRlIGJlaW5nIGNvcnJlY3Qgb24gNTYvNjcgcGlja3MgY29tcGFyZWQgdG8gb3VyIHdpbm5lciB3aG8gYWNoaWV2ZWQgYSBzb2xpZCA1MS82NywgaWYgSSBoYWQgdXNlZCBvbmx5IHRoZSBzY29yZSBwcmVkaWN0aW9ucyBvZiB0aGlzIHBhcnRpY3VsYXIgbW9kZWwgSSB3b3VsZCd2ZSBjb21lIGluIGp1c3Qgc2l4dGggcGxhY2Ugb3V0IG9mIHRoZSBzaXh0ZWVuIG9mIHVzIGluIG91ciAiYnJhY2tldCBwb29sLiIgVGhlcmUsIHRoZSBzY29yaW5nIGZhdm9ycyB0aGUgRmluYWwgRm91ciBhbmQgQ2hhbXBpb25zaGlwIG11Y2ggbW9yZSBoZWF2aWx5IHRoYW4gdGhlIGVhcmxpZXIgcm91bmRzLiBPZiB0aGUgZml2ZSB3aG8gd291bGQndmUgYmVlbiBhaGVhZCBvZiBtZSwgdGhyZWUgb2YgdGhlbSBoYWQgYSBGaW5hbCBGb3VyIG9mIGFsbCB0aGUgIzEgc2VlZHMuIEFuIGV2ZW50IHRoYXQgcHJpb3IgdG8gdGhpcyB5ZWFyIGhhZCBvbmx5IG9jY3VycmVkIG9uY2UgaW4gdGhlIGhpc3Rvcnkgb2YgKk1hcmNoIE1hZG5lc3MqLCB3YXMgc2VlbWluZ2x5IGxpa2VseSBlbm91Z2ggZm9yIGFsbCB0aHJlZSB0byBwaWNrIGl0LiBPbiB0b3Agb2YgdGhhdCwgc2l4IG91dCBvZiB0aGUgc2l4dGVlbiBoYWQgRmxvcmlkYSB3aW5uaW5nIGl0IGFsbCwgYnV0ICoqdGhlcmUncyByYW5kb21uZXNzIGluIHRoYXQgbm9ybWFsY3kqKi4gUGVyaGFwcyBpdCdzIGFuIGluZGljYXRpb24gdGhhdCB0aGUgc2VsZWN0aW9uIGNvbW1pdHRlZSBpcyBnZXR0aW5nIG11Y2ggYmV0dGVyIHdpdGggdGhlaXIgc2VlZGluZywgYW5kIHRoZSBjaGFvcyB3aWxsIHN0YXJ0IHRvIHZhbmlzaCBmcm9tIHRoZSB0b3VybmFtZW50PyBNYXliZSBOSUwgaXMgdG8gYmxhbWUsIGFuZCBjb2xsZWdlIGJhc2tldGJhbGwgaXMgZG9vbWVkIHRvIHNlZSB0aGVzZSBtb3JlIGRvbWluYW50IHRlYW1zIHJ1biB0aGUgdG91cm5hbWVudCBlYWNoIHllYXIuIFdobyBrbm93cz8gSSBjZXJ0YWlubHkgZG9uJ3QsIGJ1dCBJJ2xsIHN0aWxsIGJlIHJpZ2h0IGhlcmUgbWFraW5nIG15IHBpY2tzIGluIE1hcmNoIGFsb25nIHdpdGggbWlsbGlvbnMgb2Ygb3RoZXJzLg0KDQotLS0NCg0KIyBBYm91dCBNZQ0KDQo8YnI+DQoNCjxkaXYgc3R5bGU9ICJmbG9hdDpsZWZ0O3Bvc2l0aW9uOiByZWxhdGl2ZTsgcmlnaHQ6IDMwcHg7IHRvcDogLTdweDsiPg0KYGBge3IgZWNobz1GQUxTRSwgb3V0LndpZHRoID0gIjE3NXB4IiwgZmlnLmFsaWduPSdsZWZ0J30NCg0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoJ3BvcnRmb2xpb2ltYWdlLmpwZycpIA0KDQpgYGANCjwvZGl2Pg0KDQpJIGFtIGEgZmlyc3QgeWVhciBncmFkdWF0ZSBzdHVkZW50IHB1cnN1aW5nIG15IG1hc3RlcidzIGRlZ3JlZSBpbiBEYXRhIFNjaWVuY2UgYW5kIEFuYWx5dGljcyBhdCBDbGVtc29uIFVuaXZlcnNpdHkuIEFzIHRoZSBtaWRkbGUgb2Ygc2V2ZW4gY2hpbGRyZW4gd2hvIGFsbCBwdXJzdWVkIGRpZmZlcmVudCBhY3Rpdml0aWVzIGdyb3dpbmcgdXAgb3V0c2lkZSBvZiBQaGlsYWRlbHBoaWEsIHNwb3J0cyBoYXZlIGFsd2F5cyBiZWVuIGEgZm9jYWwgcG9pbnQgaW4gbXkgbGlmZS4gQXBwbHlpbmcgc3RhdGlzdGljcyB0byBzcG9ydHMgb3BlbmVkIG15IGV5ZXMgdG8gdGhlIHBvd2VyIG9mIGRhdGEsIGFuZCBicm91Z2h0IG1lIHRvIHdoZXJlIEkgYW0gdG9kYXkuIFRoZSAqTWFyY2ggTWFkbmVzcyogYnJhY2tldCBpbiBwYXJ0aWN1bGFyIGlzIGEgY2hhbGxlbmdlIHRoYXQgSSB3b3VsZCBsb3ZlIHRvIGNvbnRpbnVlIHRvIHRha2Ugb24gaW4gb3JkZXIgdG8gYnVpbGQgbXkgdG9vbCBzZXQgYXMgSSBkaXZlIGRlZXBlciBpbnRvIHRoaXMgZmllbGQuIFNvbWUgb2YgdGhlIGJlc3QgYW5kIGJyaWdodGVzdCBoYXZlIGNvbnRyaWJ1dGVkIHRoZWlyIG1pbmRzIHRvIHByZWRpY3RpbmcgdGhlIG91dGNvbWUgb2YgdGhpcyB0b3VybmFtZW50LCBhbmQgbm9uZSBoYXZlIHN1Y2NlZWRlZCBzbyBmYXIuIFByb2JsZW1zIGxpa2UgdGhpcyBhcmUgd2hhdCBkcml2ZXMgbXkgcGFzc2lvbiBmb3IgbGVhcm5pbmcsIGFuZCBJIGhvcGUgdG8gY29udGludWUgdG8gYm90aCBmaW5kIGFuZCBzb2x2ZSB0aGVzZSBwcm9ibGVtcyBhcyBJIG1vdmUgdG93YXJkcyBlYXJuaW5nIG15IGRlZ3JlZSBhbmQgb3V0IGludG8gdGhlIHdvcmxkLg0KDQo8YnI+DQoNCi0tLQ0KDQojIFJlZmVyZW5jZXMNCg0KKiBCZWxsQ3VydmUgLSBodHRwczovL3d3dy5yYXdidy5jb20vfmRlYW5vL2FydGljbGVzL0JlbGxDdXJ2ZS5odG1sDQoqIEtlblBvbSAtIGh0dHBzOi8va2VucG9tLmNvbS8NCiogRGF0YSBBY3Rpb24gTGFiIC0gaHR0cHM6Ly93d3cuZGF0YS1hY3Rpb24tbGFiLmNvbS8yMDIxLzExLzIxL3ByZWRpY3RpdmUtYW5hbHl0aWNzLWluLWNvbGxlZ2UtYmFza2V0YmFsbC8NCiogZ2dwbG90MjogRWxlZ2FudCBHcmFwaGljcyBmb3IgRGF0YSBBbmFseXNpcyAoM2UpIC0gaHR0cHM6Ly9nZ3Bsb3QyLWJvb2sub3JnLw0KKiBFU1BOIC0gaHR0cHM6Ly93d3cuZXNwbi5jb20vbWVucy1jb2xsZWdlLWJhc2tldGJhbGwvYnJhY2tldA0KKiBNb3VudCBTdC4gTWFyeSdzIC0gaHR0cHM6Ly9tc21hcnkuZWR1L2Fib3V0L3F1aWNrZmFjdHMuaHRtbA0KKiBNYXRoZW1hdGljcyBpbiBSIE1hcmtkb3duIC0gaHR0cHM6Ly9ycHJ1aW0uZ2l0aHViLmlvL3MzNDEvUzE5L2Zyb20tY2xhc3MvTWF0aGluUm1kLmh0bWwNCiogTkNBQSAtIGh0dHBzOi8vd3d3Lm5jYWEuY29tL25ld3MvYmFza2V0YmFsbC1tZW4vYnJhY2tldGlxLzIwMjUtMDMtMjMvbG9uZ2VzdC1uY2FhLWJyYWNrZXQtaGFzLWV2ZXItc3RheWVkLXBlcmZlY3QNCiogTkNBQSBTdGF0aXN0aWNzIC0gaHR0cHM6Ly9zdGF0cy5uY2FhLm9yZy9zZWxlY3Rpb25fcmFua2luZ3Mvbml0dHlfZ3JpdHRpZXMvMzA5Njg/dXRmOD0lRTIlOUMlOTMmY29tbWl0PVN1Ym1pdA0KKiBUZWFtUmFua2luZ3MgLSBodHRwczovL3d3dy50ZWFtcmFua2luZ3MuY29tLw0KKiBUaGUgUG93ZXIgUmFuayAtIGh0dHBzOi8vdGhlcG93ZXJyYW5rLmNvbS9jYmItYW5hbHl0aWNzLw0KKiBBcmthbnNhcyBGaWdodCAtIGh0dHBzOi8vd3d3LmFya2Fuc2FzZmlnaHQuY29tLzIwMTkvMTAvMjIvMjA5MjU3NDAvYXJrYW5zYXMtZmlnaHRzLWdsb3NzYXJ5LW9mLWFkdmFuY2VkLWJhc2tldGJhbGwtc3RhdHMjOn46dGV4dD1SZWJvdW5kcyUyMGFuZCUyMHR1cm5vdmVycyUyQyUyMG1vc3RseS4sZWZmZWN0aXZlJTIwcG9zc2Vzc2lvbiUyMHJhdGlvJTIwKEVQUikuDQoqIFI0RFMgKDJlKSAtIGh0dHBzOi8vcjRkcy5oYWRsZXkubnovDQoqIFN0YWNrT3ZlcmZsb3cgLSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NTQzMzIwOS91c2luZy1hLXNoaW55LWlucHV0LWFzLWFuLWFyZ3VtZW50LW9mLWEtZnVuY3Rpb24NCiogUGxvdHRpbmcgTm9ybWFsIERpc3RyaWJ1dGlvbnMgLSBodHRwczovL3NlYmFzdGlhbnNhdWVyLmdpdGh1Yi5pby9ub3JtYWxfY3VydmVfZ2dwbG90Mi8NCg==